這部分太多了嘁傀,自己學習的時候有側(cè)重外冀,自己整理總結(jié)的筆記是紙質(zhì)版的贩疙,學習這部分的時候主要是看了網(wǎng)上的demo,以及《Head First設(shè)計模式》(這本書我覺得推薦度一般洞渤,因為廢話實在太多了...).《大話設(shè)計模式》聽說很多人買阅嘶,之前買過《大話數(shù)據(jù)結(jié)構(gòu)》感覺大話系列的蠻容易看懂的,所以推薦下可以去看這本载迄。
面向?qū)ο笤O(shè)計模式可分為三類:(創(chuàng)建讯柔、結(jié)構(gòu)、行為)
創(chuàng)建型模式:工廠模式护昧、抽象工廠模式魂迄、生成器模式、單例模式惋耙、原型模式
結(jié)構(gòu)型模式:(類)適配器模式捣炬、(對象)適配器模式、橋接模式绽榛、組合模式湿酸、裝飾模式、外觀模式灭美、享元模式推溃、代理模式
行為模式:策略模式、模板方法模式届腐、觀察者模式铁坎、迭代子模式、責任鏈模式犁苏、命令模式厢呵、備忘錄模式、狀態(tài)模式傀顾、訪問者模式、中介者模式碌奉、解釋器模式短曾。
一寒砖、創(chuàng)建型模式:(5)
1、工廠模式【工廠模式 - 簡書】
工廠方法模式:
一個抽象產(chǎn)品類嫉拐,可以派生出多個具體產(chǎn)品類哩都。?
一個抽象工廠類,可以派生出多個具體工廠類婉徘。?
每個具體工廠類只能創(chuàng)建一個具體產(chǎn)品類的實例漠嵌。
2、抽象工廠模式:
多個抽象產(chǎn)品類盖呼,每個抽象產(chǎn)品類可以派生出多個具體產(chǎn)品類儒鹿。
一個抽象工廠類,可以派生出多個具體工廠類几晤。?
每個具體工廠類可以創(chuàng)建多個具體產(chǎn)品類的實例约炎,也就是創(chuàng)建的是一個產(chǎn)品線下的多個產(chǎn)品。?
總結(jié):
a.簡單工廠蟹瘾,不是設(shè)計模式圾浅,是一個方法,讓客戶程序從具體類解耦
b.工廠:使用繼承憾朴,把對象的創(chuàng)建委托給子類狸捕,子類實現(xiàn)工廠方法來創(chuàng)建對象;
抽象工廠:對象組合众雷,對象的創(chuàng)建被實現(xiàn)在工廠接口所暴露的方法中灸拍。創(chuàng)建相關(guān)的對象家族。
c.所有工廠模式都通過減少應用程序和具體類間的依賴促進松耦合报腔。
3株搔、生成器模式:
4、單例模式:可以保證系統(tǒng)中一個類只有一個實例而且該實例易于外界訪問纯蛾,從而方便對實例個數(shù)的控制并節(jié)約系統(tǒng)資源纤房。
私有的實例,私有的構(gòu)造方法翻诉,提供了一個公共的提供唯一實例的方法
使用:用來管理共享的資源炮姨,如數(shù)據(jù)庫連接或線程池。
設(shè)計思路
要創(chuàng)建的對象的類只有一個私有的構(gòu)造函數(shù)碰煌,構(gòu)造函數(shù)中定義了唯一的單例對象舒岸,外界只能通過getInstance()方法得到對象實例,且每次都只能生成唯一的對象芦圾。
如果不用單例模式而使用全局變量的話:
全局變量可以提供全局訪問蛾派,但不能確保只有一個實例。用許多全局變量指向許多小對象造成命名空間污染。
單例模式幾種形式:Java設(shè)計模式之單例模式詳解 - garryfu - 博客園
a.餓漢式:立即加載洪乍,類加載初期就創(chuàng)建好了靜態(tài)對象眯杏,線程安全的。
```
public class Singleton1{
? ? ? private Singleton1(){}
? private static Singleton1 single=new Singleton1();
public static Singleton1 getInstance(){
? ? return single;
? ?}
}
```
b.懶漢式:延遲加載壳澳,類似上圖岂贩,一開始對象是null,非線程安全巷波。
但會產(chǎn)生多個萎津,所以要加synchronized,加同步鎖/同步代碼塊抹镊,但運行效率低下
==>加雙重檢查和synchronized锉屈,優(yōu)化,避免了整個方法被鎖髓考,提高了執(zhí)行效率
```
雙重檢查:
public class Singleton4{
? ? ?private Singleton4(){}
private static Singleton4 single=null;
? public statci Singleton4 getInstance(){
? ? ? ? ? if(single==null)? {
? ? ? ? ? ? ? ? ?synchronized(Singleton4.class){
? ? ? ? ? ? ? ? ? ? ? ? if(single==null){
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? single=new Singleton4();? }
? ? ? ? ? ? ? ? }? ?
? ?}return single;
}??
}
```
c.靜態(tài)內(nèi)部類實現(xiàn)
d.靜態(tài)代碼塊實現(xiàn)
e.內(nèi)部枚舉類實現(xiàn)
5部念、原型模式??設(shè)計模式之原型模式 - 簡書
創(chuàng)建一個對象之后的多個對象都可以拷貝原型來創(chuàng)建。
具體實現(xiàn)是:繼承Cloneable接口氨菇,重寫Clone()方法
二儡炼、結(jié)構(gòu)型模式:(7種)
1、適配器模式:
(1)類適配器模式把一個類的接口變換成客戶端所期待的另一種接口查蓉,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作
思路:類適配器乌询,指的是適配器Adapter繼承我們的被適配者Adaptee,并實現(xiàn)目標接口Target豌研。
(2)對象適配器模式:
適配器模式把一個類的接口變換成客戶端所期待的另一種接口妹田,從而使原本因接口不匹配而無法在一起工作的兩個類能夠在一起工作。
解決設(shè)計思路:
對象適配器鹃共,簡單的說就是適配器實現(xiàn)我們的目標接口鬼佣,但是并不繼承需要被適配的類。而是通過在適配器的構(gòu)造函數(shù)中將需要被適配的類傳遞進來從而進行適配霜浴。
2晶衷、裝飾器模式:(最體現(xiàn)擴展性)
裝飾模式就是給一個對象增加一些新的功能,而且是動態(tài)的阴孟,要求裝飾對象和被裝飾對象實現(xiàn)同一個接口晌纫,裝飾對象持有被裝飾對象的實例,關(guān)系圖如下:
可以用一個或多個裝飾者包裝一個對象永丝。
裝飾者和被裝飾者對象有相同的超類型锹漱,所以在任何需要原始對象(被包裝)的場合,可用裝飾過的對象代替它慕嚷。
裝飾者可以在所委托被裝飾者的行為之前/之后哥牍,加上自己的行為毕泌,以達到特定目的。
調(diào)用時:被裝飾者在最底層砂心,被裝飾者一層層包裝懈词,可以包裝多次。
```
Beverage? b=new Beverage();
b=new Mocha(b);
b=new Mocha(b)辩诞;
b=new Milk(b);
System.out.println(b.getDes()+ b.cost());
```
擴展:java.io包使用了裝飾者模式
【抽象組件:InputSream
具體的抽象組件/被裝飾類:FileInputStream纺涤、StringBufferInputStream译暂、ByteArrayInputStream...
抽象裝飾者:FilterInputStream
具體組件/裝飾類:PushbackInputStream、BufferedInputStream撩炊、DataInputStream
】
缺點是:設(shè)計時會加入大量小類外永。在實例化組件時,還要把此組件包裝進去拧咳,增加了代碼復雜度伯顶。
優(yōu)點:適合建立有彈性的設(shè)計、維持開放-關(guān)閉原則骆膝。
3祭衩、代理模式(Proxy):
代理模式就是多一個代理類出來,替原對象進行一些操作阅签。
4掐暮、外觀模式:
外觀模式是為了解決類與類之家的依賴關(guān)系的,像spring一樣政钟,可以將類和類之間的關(guān)系配置到配置文件中路克,而外觀模式就是將他們的關(guān)系放在一個Facade類中,降低了類類之間的耦合度养交,該模式中沒有涉及到接口精算,看下類圖:(我們以一個計算機的啟動過程為例)
5、橋接模式:
橋接模式就是把事物和其具體實現(xiàn)分開碎连,使他們可以各自獨立的變化灰羽。橋接的用意是:將抽象化與實現(xiàn)化解耦,使得二者可以獨立變化破花。
像我們常用的JDBC橋DriverManager一樣谦趣,JDBC進行連接數(shù)據(jù)庫的時候,在各個數(shù)據(jù)庫之間進行切換座每,基本不需要動太多的代碼前鹅,甚至絲毫不用動,原因就是JDBC提供統(tǒng)一接口峭梳,每個數(shù)據(jù)庫提供各自的實現(xiàn)舰绘,用一個叫做數(shù)據(jù)庫驅(qū)動的程序來橋接就行了蹂喻。我們來看看關(guān)系圖:
6、組合模式:
(1)安全組合模式:將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)捂寿。Composite使得用戶對單個對象和組合對象的使用具有一致性口四。
(2)一致性組合模式:
7、享元模式:
享元模式的主要目的是實現(xiàn)對象的共享秦陋,即共享池蔓彩,當系統(tǒng)中對象多的時候可以減少內(nèi)存的開銷,通常與工廠模式一起使用驳概。
三赤嚼、行為型模式:(11)
1、策略模式
2顺又、模板方法模式
3更卒、觀察者模式:(出版者/主題+訂閱者/觀察者)
a.? 定義了對象之間的一對多依賴,一個對象改變狀態(tài)時稚照,它的所有依賴者都會收到通知并自動更新蹂空。
在subject接口和observer接口中直接寫就可以了。
在concreteSubject類果录,要實現(xiàn)subject接口上枕,可以創(chuàng)建一個ArrayList<Observer> 存放的是所有注冊該主題的觀察者,如果register()就是往list中add()一個observer雕憔,remove()就是remove一個observer姿骏,notify()相當于遍歷整個list,對每個observer對象進行update()斤彼。
在concreteObserver類分瘦,實現(xiàn)Observer接口,有一個Subject的對象琉苇,其構(gòu)造函數(shù)嘲玫,相當于注冊了一個新的觀察者,所以是需要subject需要注冊的主題為傳入?yún)?shù)并扇,并調(diào)用其的register()方法去团,相當于在該主題注冊了新對象。其update()方法穷蛹,當其被concreteSubject的實體對象調(diào)用時土陪,會傳入?yún)?shù),也就是給這個觀察者對象做了通知肴熏。
b.? ?此外9砣浮!M芾簟源哩!java API有內(nèi)置的觀察者模式鞋吉,java.util包有包含基本的Observer接口和Observable類,類似于Subject接口和Observer接口励烦,可以進行push()谓着、pull()傳送數(shù)據(jù)。
Observable接口的方法:addObserver()? deleteObserver()? notifyObserver()? setChanged()
現(xiàn)在concreteSubject類繼承Observable類坛掠,并繼承其addr赊锚、remove、notify()等方法屉栓。
對concreteObserver改抡,要把對象變成觀察者:實現(xiàn)Observer接口,然后構(gòu)造方法中傳入observer對象系瓢,并調(diào)用其addObserver()方法;不想當觀察者句灌,則調(diào)用deleteObserver()
觀察者送出通知:在concretObserver類觀察者中構(gòu)造concreteSubject類夷陋,調(diào)用其setChanged()方法,標記狀態(tài)已經(jīng)改變胰锌;調(diào)用其notifyObservers()或notifyObservers(Object arg)//傳任何數(shù)據(jù)對象
【推和拉:
拉:
setChanged():改變狀態(tài)骗绕,到達某種條件,才調(diào)用該方法资昧,使changed變?yōu)閠rue酬土,進行通知。這樣可以避免不必要的通知格带。這個時候傳送通知的方式是“拉”??
notyfyObservers(Object arg):源代碼會先判斷是否發(fā)生了changed撤缴,true才通知觀察者,通知后將changed標志又設(shè)回false
推:
沒有setChanged()叽唱,和之前一樣屈呕,就是直接notify(),不用通知者自己來調(diào)用setChanged()和notify()的棺亭,就是推虎眨。
】
觀察者接收通知:同之前的update(Observerable o,Object arg)? //傳任何數(shù)據(jù)對象
但是!镶摘!
1嗽桩、java.util.Observable是一個類,因此某類要同時有Observable和其他超類行為凄敢,就會困難(因為單繼承)碌冶,限制了其復用潛力。
2贡未、除非繼承Observable類种樱,否則無法創(chuàng)建Observable的實例并組合到你自己的對象中(特別是setChanged()是protected的)
c.? JDK中的使用:
JButton
4蒙袍、迭代子模式、
5嫩挤、責任鏈模式
6害幅、命令模式:將請求封裝成對象,以便使用不同的請求岂昭、隊列或者日志來參數(shù)化其他對象以现。
命令對象封裝動作和接收者,而只暴露出execute()约啊,當該方法調(diào)用邑遏,接收者會進行動作。
Client:是測試類
Command接口:只有execute()方法
ConcreteCommand類:具體命令恰矩,其中有Receiver具體接受類對象记盒,實現(xiàn)了Command接口,其方法主要是重寫了execute()外傅,讓Receiver對象實現(xiàn)一個具體的命令纪吮。
Receiver:也就是命令的執(zhí)行對象,ConcreteCommand將會調(diào)用它
Invoke類:調(diào)用者,其有Command對象萎胰,在setCommand(command)方法中傳入一個具體的concreteCommand對象碾盟,設(shè)置具體的命令;其還有另外一個方法技竟,用于調(diào)用concreteCommand對象的execute()方法
例子:遙控器開燈
應用:隊列請求冰肴、日志請求
7、備忘錄模式
8榔组、狀態(tài)模式
9熙尉、訪問者模式
10、中介者模式
11瓷患、解釋器模式