由於設計模式篇幅比較大,如果在一篇文章講完所有的設計模式的話不利於閱讀。於是我把它分為三篇文章
設計模式都是比較抽象的概念,所以大家一定要確保看懂類圖而后再自己寫代碼加強記憶。
概述
結構型模式共七種:
- 適配器模式(Adapter)
- 外觀模式(Facade)
- 橋接模式(Bridge)
- 裝飾器模式(Decorator)
- 代理模式(Proxy)
- 享元模式(Flyweight)
- 組合模式(Composite)
其中又分為
接口適配:適配器、外觀、橋接模式
行為擴展:裝飾
性能與對象訪問:代理、享元模式
抽象集合:組合模式
一、適配器模式
定義:將一個類的接口轉換成客戶希望的另外一個接口,Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以一起工作。
角色:適配器(Adapter)、被適配類、對象(Adaptee)
理解:客戶需要Target,現實只有Adaptee,可以用一個實現Target協議的適配器通過類繼承或者對象組合類獲得被Adaptee。
類圖:
例子代碼:
// 原有的接口,不符合客戶要求
interface IOrigin{ public void deal(); }
// 定義一個符合客戶要求的新接口 interface ITarget{ public void newDeal(int type); } class Target implements ITarget{ private IOrigin origin; public void newDeal(int type){ if (type==0){ origin.deal(); }else{ //做其他 } } } public class TestAdapter { public void test(){ // 原來是IOrigin接口但是不符合我要求,所以用ITarget適配一下 // ITarget target = new Target(); target.newDeal(1); } }
二、外觀模式
定義:為子系統中一組不同的接口提供統一的接口
什么時候用:1.子系統正逐漸變得復雜,應用模式的過程中演化出許多類。可以使用外觀為這些子系統類提供一個較簡單的接口。2.可以使用外觀對子系統分層,每個字系統級別有一個外觀做為入口。讓她們通過外觀進行通信,可以簡化他們的依賴關系。
類圖:
例子代碼:
// 一個維修汽車廠系統包括,小車維修、公交維修、驗收 // 小車 class Car{ // 維修 public void repair(); } // 公車 class Bus{ // 維修 public void repair(); } // 維修人員 class Repairer{ public void doRepair(); } // 驗收人員 class Checker{ public void doCheck(); } // 老板不可能管的那么細,他需要雇佣一個經理 class Leader{ private Repairer repairer; private Checker checker; public void repair(); public boolean check(); } public class TestFacade { public void test(){ // 老板接一個單子時,直接叫經理去修車,然后再問經理是否完成,這個經理就是一個外觀 Leader leader = new Leader(); // 通知經理修車,不管經理下面有多少個維修人員,驗收人員 leader.repair(); boolean isOk = leader.check(); } }
三、橋接模式
定義:將抽象部分與它的實現部分分離,使它可以獨立的變更
角色:抽象層接口(Abstraction)、具體抽象層、實現者接口、具體實現者。
理解:這里有兩個接口,一個是抽象層接口Abstraction,一個是Implementor接口,其中Abstraction持有Implementor的引用。客戶端通過Abstraction來連接Implementor,以后Implementor可以動態的改變而不影響Abstraction。
什么時候用:1.不想在抽象與實現之間形成固定的綁定關系(這樣就能在運行時切換實現)。2.抽象與實現都應可以通過子類化獨立進行擴展。
3.對抽象的實現進行修改不應影響客戶端代碼。4.如果每個實現需要額外的子類以細化抽象,則說明有必要把它們分成兩個部分。5.想在帶有不同抽象接口的多個對象之間共享一個實現。
類圖:
例子代碼:
interface ILeader{ public void doSomething(); } class LeaderA implements ILeader{ @Override public void doSomething() {} } class LeaderB implements ILeader{ @Override public void doSomething() {} } class Boss { ILeader leader; public void setLeader(ILeader leader) { this.leader = leader; } public void doSomething(){ this.leader.doSomething(); } } public class TestBirdge { public void test(){ Boss boss = new Boss(); LeaderA leaderA = new LeaderA(); boss.setLeader(leaderA); boss.doSomething(); // 當某個經理離職的時候,老板可以再找一個有經驗的經理來做事, LeaderB leaderB = new LeaderB(); boss.setLeader(leaderB); boss.doSomething(); } }
四、裝飾器模式
定義:動態的給對象添加一些額外的責任,就增加功能來說,裝飾比生成子類更為靈活。
角色:組件接口(Component)、具體的組件、繼承至Component的修飾接口(Decorator)、具體的修飾
理解:修飾接口Decorator繼承Component,並持有Component的一個引用,所以起到了復用Component並增加新的功能。
什么時候用:1.想要在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。2.想要擴展一個類的行為,卻做不到。類定義可能被隱藏,無法進行子類化;或者對類的每個行為的擴展,哦支持每種功能組合,將產生大量的子類。
類圖:
例子代碼:
interface ICar{ public void run(); } class Car implements ICar{ @Override public void run() { } } // 現在想給汽車添加 氮氣加速 // 下面用子類化方式實現 class SubClassCar extends Car{ @Override public void run() { this.addNitrogen(); super.run(); } public void addNitrogen(){} } // 下面用裝飾模式實現 class DecoratorCar implements ICar{ private Car car; @Override public void run() { this.addNitrogen(); car.run(); } public void addNitrogen(){} } public class TestDecorator { public void test(){ } }
五、代理模式
定義:為其他對象提供一種代理以控制對這個對象的訪問
角色:客戶端(Client)、目標接口(subject)代理對象(Proxy)、真正的目標對象(RealSubject)
虛擬代理:客戶端擁有Subject的引用,其實就是Proxy對象,Proxy對象持有RealSubject的引用,調用Proxy.request Proxy會實際調用RealSubject.request
類圖:
例子代碼:
// 一個顧客要買房 class Customer{ public void sellHouse(){ } } class Proxy { private Customer customer; public void buyHouse(){ customer.sellHouse(); } } public class TestProxy { public void test(){ // 一個買家要買房的話直接跟中介(代理)大交道就可以了 Proxy proxy = new Proxy(); proxy.buyHouse(); } }
六、組合模式
定義:將對象組合成樹形結構以表示’部分-整體’的層次結構。組合模式使得用戶對單個對象和組合對象的使用具有一致性。
理解:組合模式讓我們可以把相同的基類型的對象組合到樹狀結構中,其中父節點包含同類型的子節點。
什么時候用:1.想獲得對象抽象的樹形表示(部分-整體層次結構)。2.想讓客戶端統一處理組合結構中的所有對象。
類圖:
七、享元模式
定義:運用共享技術有效地支持大量細粒度的對象。
角色:享元池、享元接口、具體享元對象
理解:客戶端需要享元對象時,先去享元池尋找,如果找到了就直接復用,如果沒有找到就創建享元對象並保存到享元池。
類圖: