對象相關(guān)的三類職責:
對象本身所具有的職責
創(chuàng)建對象的職責
使用對象的職責
java中創(chuàng)建對象的方式:new、反射欢峰、clone()葬荷、序列化、工廠類纽帖。
class LoginAction{
private UserDao userDao;
public LoginAction(){
//創(chuàng)建和使用耦合
userDao = new JDBCUserDao();
}
public void execute(){
userDao.findUserById();
}
}
兩個類的關(guān)系應該僅僅是A創(chuàng)建B或者A使用B宠漩,而不是兩種都有。
創(chuàng)建與使用分離:防止用來實例化一個類的數(shù)據(jù)和代碼在多個類中到處都是懊直,可以將有關(guān)創(chuàng)建的知識搬移到一個工廠類中扒吁。有時候我們創(chuàng)建一個對象不只是簡單調(diào)用構(gòu)造函數(shù),還需要一些參數(shù)室囊,配置環(huán)境雕崩。
如果產(chǎn)品類簡單,不存在太多變數(shù)融撞,構(gòu)造簡單盼铁,無需提供工廠類。如String類尝偎。
一捉貌、簡單工廠模式
定義一個工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實例,被創(chuàng)建的實例通常都具有共同的父類趁窃。因為在簡單工廠模式中用于創(chuàng)建實例的方法是靜態(tài)(static)方法牧挣,因此簡單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式醒陆。
使用時瀑构,首先對產(chǎn)品類進行重構(gòu),根據(jù)實際情況設(shè)計一個產(chǎn)品層次結(jié)構(gòu)刨摩,將所有產(chǎn)品類的公共代碼移至抽象產(chǎn)品類寺晌,簡單工廠方法根據(jù)傳入的參數(shù)不同可以創(chuàng)建不同的產(chǎn)品對象。
問題:客戶端創(chuàng)建具體產(chǎn)品時澡刹,需要修改簡單工廠方法的參數(shù)呻征,違反“開閉原則”。
改進:將參數(shù)存儲在XML或properties的配置文件中罢浇,利用工具類直接讀取參數(shù)陆赋。
簡單工廠模式的簡化:將抽象產(chǎn)品類和工廠類合并。
主要優(yōu)點
1嚷闭、對象創(chuàng)建和使用的分離攒岛。
2、客戶端只需要知道具體產(chǎn)品類對應的參數(shù)胞锰,無需知道具體產(chǎn)品類的類名灾锯。
3、引入配置文件嗅榕,不修改客戶端代碼的情況下更換具體產(chǎn)品類顺饮。
主要缺點
1、工廠類集中所有產(chǎn)品的創(chuàng)建邏輯凌那,職責過重领突,一旦不正常,整個系統(tǒng)都受影響案怯。
2君旦、增加類的數(shù)量,增加復雜度和理解難度嘲碱。
3金砍、新增產(chǎn)品要修改工廠類邏輯,產(chǎn)品類較多時麦锯,可能造成邏輯過于復雜恕稠,不利于系統(tǒng)擴展和維護。
4扶欣、簡單工廠模式使用靜態(tài)工廠方法鹅巍,造成工廠角色無法形成基于繼承的等級結(jié)構(gòu)千扶。
適用場景:
1、工廠類負責創(chuàng)建的對象比較少骆捧,由于創(chuàng)建的對象較少澎羞,不會造成工廠方法中的業(yè)務邏輯太過復雜。
2敛苇、客戶端只知道傳入工廠類的參數(shù)妆绞,對于如何創(chuàng)建對象并不關(guān)心。
二枫攀、工廠方法模式
問題:
1括饶、工廠類過于龐大,包含大量if...else..代碼来涨,職責過大图焰,不利于維護和測試。
2蹦掐、新增日志記錄器技羔,需要修改工廠業(yè)務邏輯。
定義一個用于創(chuàng)建對象的接口笤闯,讓子類決定將哪一個類實例化堕阔。工廠方法模式讓一個類的實例化延遲到其子類棍厂。工廠方法模式又簡稱為工廠模式(Factory Pattern)颗味,又可稱作虛擬構(gòu)造器模式(Virtual Constructor Pattern)或多態(tài)工廠模式(Polymorphic Factory Pattern)。工廠方法模式是一種類創(chuàng)建型模式牺弹。
具體工廠類在實現(xiàn)工廠方法時除了創(chuàng)建具體產(chǎn)品對象之外浦马,還可以負責產(chǎn)品對象的初始化工作以及一些資源和環(huán)境配置工作,例如連接數(shù)據(jù)庫张漂、創(chuàng)建文件等晶默。
反射與配置文件
在客戶端代碼中不使用new創(chuàng)建工廠對象,將具體的工廠類的類名存儲在配置文件中航攒,利用Java反射根據(jù)類名字符串生成對象磺陡。
問題:為什么不直接在客戶端通過反射生成產(chǎn)品對象?
工廠除了對象的創(chuàng)建和使用分離漠畜,還有創(chuàng)建前后初始化(配置環(huán)境币他、設(shè)置參數(shù)等)代碼封裝到工廠中。
重載的工廠方法
提供默認參數(shù)憔狞、配置參數(shù)蝴悉、文件路徑等方式初始化日志記錄器。
工廠方法的隱藏
在工廠類中直接調(diào)用產(chǎn)品類的業(yè)務方法(writeLogger())瘾敢,客戶端無須調(diào)用工廠方法創(chuàng)建產(chǎn)品拍冠。
主要優(yōu)點
1尿这、工廠方法創(chuàng)建產(chǎn)品,向客戶隱藏了具體哪種產(chǎn)品類被實例化庆杜,用戶只需要關(guān)心所需要產(chǎn)品對應的工廠射众,無須關(guān)心創(chuàng)建細節(jié)。
2欣福、基于工廠角色和產(chǎn)品角色的多態(tài)性是工廠方法模式的關(guān)鍵责球。
3、加入新產(chǎn)品時拓劝,無須修改抽象工廠雏逾、抽象產(chǎn)品、客戶端和其他具體工廠和具體產(chǎn)品郑临,完全符合“開閉原則”栖博。
主要缺點
1、添加新產(chǎn)品時厢洞,類的個數(shù)成對增加仇让,給系統(tǒng)帶來額外開銷。
2躺翻、引入抽象層丧叽,增加抽象性和理解難度,使用DOM和反射等技術(shù)公你,增加了實現(xiàn)難度踊淳。
適用場景
1、客戶端不知道它所需要的對象類陕靠。
2迂尝、抽象工廠類通過其子類來指定創(chuàng)建哪個對象。(多態(tài)性和里氏替換原則)
三剪芥、抽象工廠模式
工廠方法模式引入工廠等級結(jié)構(gòu)垄开,解決了簡單工廠模式中工廠類職責太重的問題,但每個工廠只生產(chǎn)一類產(chǎn)品税肪,可能導致系統(tǒng)中存在大量的工廠類溉躲,勢必會增加系統(tǒng)開銷。
“將一些相關(guān)的產(chǎn)品組成一個“產(chǎn)品簇”益兄,由一個工廠來統(tǒng)一生產(chǎn)锻梳。”(Java語言的AWT包)
產(chǎn)品等級結(jié)構(gòu)與產(chǎn)品簇
(1)產(chǎn)品等級結(jié)構(gòu):產(chǎn)品的繼承結(jié)構(gòu)偏塞。如抽象電視機是父類唱蒸,而具體品牌的電視機是其子類。
(2)產(chǎn)品族:由同一個工廠生產(chǎn)的灸叼,位于不同產(chǎn)品等級結(jié)構(gòu)中的一組產(chǎn)品神汹。如海爾電器工廠生產(chǎn)的海爾電視機庆捺、海爾電冰箱構(gòu)成一個產(chǎn)品族。
不同顏色的多個正方形屁魏、圓形和橢圓形分別構(gòu)成了三個不同的產(chǎn)品等級結(jié)構(gòu)滔以,而相同顏色的正方形、圓形和橢圓形構(gòu)成了一個產(chǎn)品族氓拼,每一個形狀對象都位于某個產(chǎn)品族你画,并屬于某個產(chǎn)品等級結(jié)構(gòu)。
抽象工廠模式是所有工廠模式中最為抽象和最具一般性的一種形式
當一個工廠等級結(jié)構(gòu)可以創(chuàng)建出分屬于不同產(chǎn)品等級結(jié)構(gòu)的一個產(chǎn)品族中所有對象時桃漾,抽象工廠模式比工廠方法模式更為簡單坏匪、效率。(減少類的個數(shù))
提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口撬统,而無須指定它們具體的類适滓。抽象工廠模式又稱為Kit模式,它是一種對象創(chuàng)建型模式恋追。為創(chuàng)建一組對象提供了一種解決方案凭迹。
引入XMLUtil工具類和配置文件,讓系統(tǒng)具備良好的靈活性和可擴展性苦囱。
在實際環(huán)境中嗅绸,我們可以提供可視化界面,例如菜單或者窗口來修改配置文件撕彤,用戶無須直接修改配置文件鱼鸠。
如果需要增加新的皮膚,只需增加一族新的具體組件并對應提供一個新的具體工廠喉刘。
“開閉原則”的傾斜性
抽象工廠模式最大的缺點 :在增加新的產(chǎn)品族很方便瞧柔,但是增加新的產(chǎn)品等級結(jié)構(gòu)很麻煩漆弄,抽象工廠模式的這種性質(zhì)稱為“開閉原則”的傾斜性睦裳。
1、增加產(chǎn)品族:對于增加新的產(chǎn)品族撼唾,抽象工廠模式很好地支持了“開閉原則”廉邑,只需要增加具體產(chǎn)品并對應增加一個新的具體工廠,對已有代碼無須做任何修改倒谷。
2蛛蒙、增加新的產(chǎn)品等級結(jié)構(gòu):對于增加新的產(chǎn)品等級結(jié)構(gòu),需要修改所有的工廠角色渤愁,包括抽象工廠類牵祟,在所有的工廠類中都需要增加生產(chǎn)新產(chǎn)品的方法,違背了“開閉原則”抖格。
主要優(yōu)點
1诺苹、
隔離了具體類的生成咕晋,使得客戶并不需要知道什么被創(chuàng)建。
2收奔、當一個產(chǎn)品族中的多個對象被設(shè)計成一起工作時掌呜,它能夠保證客戶端始終只使用同一個產(chǎn)品族中的對象。
3坪哄、加新的產(chǎn)品族很方便质蕉,無須修改已有系統(tǒng),符合“開閉原則”翩肌。
主要缺點
增加新的產(chǎn)品等級結(jié)構(gòu)麻煩模暗,需要對原有系統(tǒng)進行較大的修改,甚至需要修改抽象層代碼念祭,這顯然會帶來較大的不便汰蓉,違背了“開閉原則”。
使用場景
1棒卷、一個系統(tǒng)不應當依賴于產(chǎn)品類實例如何被創(chuàng)建顾孽、組合和表達的細節(jié)。
2比规、系統(tǒng)中有多于一個的產(chǎn)品族若厚,而每次只使用其中某一產(chǎn)品族。
3蜒什、屬于同一個產(chǎn)品族的產(chǎn)品將在一起使用测秸,這一約束必須在系統(tǒng)的設(shè)計中體現(xiàn)出來。同一個產(chǎn)品族中的產(chǎn)品可以是沒有任何關(guān)系的對象灾常,但是它們都具有一些共同的約束霎冯,如同一操作系統(tǒng)下的按鈕和文本框,按鈕與文本框之間沒有直接關(guān)系钞瀑,但它們都是屬于某一操作系統(tǒng)的沈撞,此時具有一個共同的約束條件:操作系統(tǒng)的類型。
4雕什、產(chǎn)品等級結(jié)構(gòu)穩(wěn)定缠俺,設(shè)計完成之后,不會向系統(tǒng)中增加新的產(chǎn)品等級結(jié)構(gòu)或者刪除已有的產(chǎn)品等級結(jié)構(gòu)贷岸。