8.6.4.1請實現一個線程安全的單例模式。
1 public class MailListReader {
2 private static MailListReader reader = null;
3 private MailListReader(){}//構造函數私有
4 public static MailListReader getInstance() {
5 if(singleton == null){
6 synchronized (Singleton.class){
7 if(singleton == null){
8 singleton = new Singleton();
9 }
10 }
11 }
12 return reader;
13 }
14 //省略提供郵件列表的方法
15 }
8.6.4.2工廠模式有哪幾類?使用工廠模式最主要的好處是什么?你在項目里是怎么使用工廠模式的?
工廠模式(Factory Method)是用來向使用者屏蔽創建對象的細節。之前我們在講SAX解析XML文件時,已經用到過工廠模式,當時我們是通過如下代碼用SAXParserFacotry這個工廠對象來創建用於解析的parse對象,代碼如下所示。
1 SAXParserFactory factory = SAXParserFactory.newInstance();
2 SAXParser parser = factory.newSAXParser();
作為使用者,我們只要能得到parser對象進行后繼的解析動作,至於parser對象是如何創建的,我們不需要,也不應管。如果不用工廠模式,那么我們還得親自關注如何創建parser對象,比如得考慮創建時傳入的參數,以及是否改用“池”的方式來創建從而提升效率。
這樣親力親為的后果是,會讓使用和創建parser對象的代碼耦合度很高,這樣一旦創建parser的方法發生改變,比如日后需要傳入不同的參數,那么使用parser的代碼也需要對應修改。
大家別以為增加修改量沒什么大不了,如果我們在某個模塊里修改了代碼,哪怕這個修改點再小,也得經過完整的測試才能把這段代碼放入生產環境,這是需要工作量的。如果我們把“使用”和“創建”對象放在一個模塊里,那么“使用”部分的代碼也得測試(雖然沒改),但我們通過了工廠模式分離了兩者,那么只需要測“創建”模塊,就可以減少工作量了。
更多內容請看本書8.2.2到8.2.4部分
8.6.4.3 你在平時的開發過程中用過哪些設計模式?
在本書的第8章里,已經列了關於觀察者等模式的說辭,下面,我們進一步給出講述設計模式(乃至設計思想)的說辭。
我們在8.5.3講述里氏替換原則時,已經給出了“在面試中不露痕跡引出設計模式話題“的一些方法,這里我們將給出展示自己 設計模式能力的方法,大家一定得在面試前,根據這里給出的四個關鍵說明點做好充分的准備,臨時准備一定是達不到好的效果的。
說明點一,通過案例場景引出你准備說的模式。
這里可以從你簡歷中的最近做的一個項目里提煉一個例子,比如就拿觀察者模式里的“牛人發文章郵件通知粉絲”為例,大家可以先描述下項目的場景(也就是要解決的實際問題)。
說明點二,引出待使用的設計模式。
這里需要說出你引用的場景和設計模式的切合點,比如這里需求的關鍵點在於“狀態改變后需通知依賴對象”,這和觀察者模式的適用場景一致。
說明點三,結合項目實際,通過代碼等方式說明設計模式。
比如這里可以通過項目里的相關類,以及類之間的繼承和調用關系來說明你是怎么實現觀察者模式的,比如通知類、文章管理類和調用類分別是如何實現的,同時說明它們之間的調用關系。
說明點四,結合設計原則,說出自己對設計模式的理解。
最好再說下自己對設計模式的理解,否則你的層次可能只停留在“會用設計模式解決實際問題”(當然這也已經不錯了),而不是“具有一定的架構設計和優化能力”(這是更好的評價)。
這里給出一些“出彩”的語句給大家參考。
1 其實我們使用設計模式的根本原因是提升項目的可維護性。(大家都知道,但你得說)
2 我們在解決這個(你舉的例子)問題時,除了用到設計模式之外,還會盡量注意設計模式背后蘊含的思想,比如在設計觀察者類時,我們不在其中放其它種類的業務代碼,這符合單一職責模式,而且我們定義類之間的關系時,會遵循“合成復用原則“,只在具有從屬關系的類之間才使用繼承,否則會使用聚合或組合。(最好再通過實例說明,如果可以,再結合項目實例引入其它的原則)
3 在項目里,我們經常會收到需求變更,當我們引入設計模式(或原則)后,發現能讓項目擁抱修改。
隨后舉個例子說明,比如之前的代碼沒有很好遵循單一職責模式,在一些重要方法里放了多種邏輯,在幾次修改后,我們痛定思痛決定重構代碼,重構后的方法里只包含了一類邏輯,之后再修改的時候,我們的測試工作量就能大幅度降低了。
4 我現在感覺是,設計模式不僅能給出具體的解決方案,還能提供優化系統架構的思路,所以在項目里,我們一般不會只用其中某個,而會根據一些原則來優化我們的代碼。
比如在定義模塊和方法時,根據單一職責原則,我們盡量只在其中引入一類邏輯,在定義子類方法時,根據里氏替換原則,如果子類要擴展功能,我們是會在其中添加新的方法,而不是覆蓋父類的非抽象方法,又如,根據合成復用原則,我們只把具有邏輯從屬關系的類定義成父子類,否則是用組合或聚合來定義類之間的耦合關系。
總之,大家如果能在面試中按上述四個“說明點”層層遞進地展示自己設計模式方面的能力,就一定能得到“精通設計模式”乃至“有一定的系統架構設計和優化經驗”之類的評價,這類評語在同等條件下能很大程度地幫助大家成功地在競爭者中脫穎而出,從而得到心儀的崗位。