裝飾器模式詳解(UML、原理、使用、與代理模式的區別等)
來源:mikechen的網際網路架構
設計模式是寫出優秀程式的保障,與架構能力與閱讀原始碼的能力息息相關,對程式設計師來說非常重要,非常值得深入學習。
前面,我們介紹了:
7 大設計原則(41張圖解、2萬多字)
5 大建立型設計模式總結,20 張圖徹底掌握
今天我們主要介紹裝飾器模式,裝飾器是繼承的有力補充,比繼承靈活,在不改變原有物件的情況下,動態的給一個物件擴充套件功能,即插即用。
裝飾器模式(Decorator)是作為現有的類的一個包裝,它允許向一個現有的物件新增新的功能,同時又不改變其結構,屬於結構型模式。
舉個例子:我們去買煎餅,可以在煎餅中新增雞蛋、肉鬆或培根......。但不管新增什麼,它仍然是一個煎餅。
除此之外,生活中還有很多類似裝飾器模式的例子,例如火鍋中可以新增毛肚、鵝腸、雞毛菜等不同菜品......
裝飾器模式的 UML 類圖:
裝飾器模式的結構:
抽象構件(Component):定義一個抽象介面以規範準備接收附加責任的物件;
具體構件(ConcreteComponent):實現抽象構件,透過裝飾角色為其新增一些職責;
裝飾器(Decorator):抽象裝飾,繼承抽象構件,幷包含具體構件的例項,可以透過其子類擴充套件具體構件的功能;
具體裝飾(ConcreteDecorator):實現抽象裝飾的相關方法,並給具體構件物件新增附加的責任。
通常情況下,擴充套件一個類的功能會使用繼承方式來實現。由於繼承具有靜態特徵、耦合度高,隨著擴充套件功能的增多,子類就會很膨脹。
裝飾器模式是繼承的有力補充,比繼承靈活,可以在不改變原有物件的情況下,動態的給一個物件擴充套件功能,即插即用。
接下來,我們來看看裝飾器模式的具體實現,仍然使用生活中的例子。
程式碼示例:用房子作為目標。
1)房子介面:House
/** * 目標介面:房子 */public interface House { void output();}
2)具體的房子:ChenRuiHouse
/** * 房子實現類 */public class DonghaoHouse implements House { @Override public void output() { System.out.println("這是陳睿的房子"); }}
3)具體的房子:MikeChenHouse
/** * 房子實現類 */public class MikeChenHouse implements House { @Override public void output() { System.out.println("這是MikeChen的房子"); }}
4)裝飾器:Decorator
public class Decorator implements House { private House house; public Decorator(House house){ this.house = house; } @Override public void output() { System.out.println("這是針對房子的前段裝飾增強"); house.output(); System.out.println("這是針對房子的後段裝飾增強"); }}
5)測試類
public class Clienter { public static void main(String[] args) { House ChenRuiHouse = new ChenRuiHouse(); House decorator = new Decorator(ChenRuiHouse); decorator.output(); }}
結果:
這是針對房子的前段裝飾增強這是陳睿的房子這是針對房子的後段裝飾增強
裝飾器模式的常見使用場景:
當需要給一個現有類新增附加職責,而又不能採用生成子類的方法進行擴充時。例如,該類被隱藏或者該類是終極類或者採用繼承方式會產生大量的子類;
當需要透過對現有的一組基本功能進行排列組合而產生非常多的功能時,採用繼承關係很難實現,而採用裝飾器模式卻很好實現;
當物件的功能要求可以動態地新增,也可以再動態地撤銷時。
在 Java 中,裝飾器模式最著名的應用是 Java I/O 標準庫的設計。
例如,
InputStream 的子類 FilterInputStream,OutputStream 的子類 FilterOutputStream,Reader 的子類 BufferedReader 以及 FilterReader等,它們都是抽象裝飾類。
下面程式碼是為 FileReader 增加緩衝區,而採用的裝飾類 BufferedReader 的例子:
BufferedReader in = new BufferedReader(new FileReader("filename.txt"));String s = in.readLine();
裝飾器模式的優點:
裝飾類和被裝飾類可以獨立發展,不會相互耦合,互相都不用知道對方的存在;
裝飾器是繼承的有力補充,比繼承靈活,在不改變原有物件的情況下,動態的給一個物件擴充套件功能,即插即用;
透過使用不用裝飾類及這些裝飾類的排列組合,可以實現不同效果。
裝飾器模式的缺點:
裝飾器模式會增加許多子類,多層裝飾比較複雜,過度使用會增加程式的複雜性,不利於我們除錯。
裝飾器模式與代理模式的區別,主要體現在概念及使用等方面。
1) 概念方面
代理是全權代理,目標根本不對外,全部由代理類來完成;
裝飾是增強,是輔助,目標仍然可以自行對外提供服務,裝飾器只起增強作用。
代理模式:
public class Proxy implements House { private House house; public Decorator(){ this.house = new DonghaoHouse(); } @Override public void output() { System.out.println("這是針對目標的前段增強"); house.output(); System.out.println("這是針對目標的後段增強"); }}
代理模式針對的目標實現類是固定的,代理中持有的目標例項是自己建立的。
裝飾模式:
public class Decorator implements House { private House house; public Decorator(House house){ this.house = house; } @Override public void output() { System.out.println("這是針對房子的前段裝飾增強"); house.output(); System.out.println("這是針對房子的後段裝飾增強"); }}
裝飾器模式可以隨意指定目標實現類,即目標是可以自由擴充套件的,裝飾器中持有的目標例項是從構造器傳入的。
2) 使用場景
兩者都是對類的方法進行擴充套件,但使用場景不同:
裝飾器模式
強調的是增強自身,在被裝飾之後,能夠在被增強的類上使用增強後的功能。在增強後,你還是你,只不過能力更強了而已。
代理模式
強調要讓別人幫你去做一些本身與你業務沒有太多關係的職責(記錄日誌、設定快取)。
代理模式是為了實現物件的控制,因為被代理的物件往往難以直接獲得,或者是其內部不想暴露出來。
裝飾器模式應當為所裝飾的物件提供增強功能,而代理模式對所代理物件的使用施加控制,並不提供物件本身的增強功能。
透過本文,我們瞭解並掌握了裝飾器模式,包括裝飾器模式的概念、作用、結構、使用場景、優缺點及應用等。
設計模式的重要性就不多說了,只有我們瞭解每一種設計模式,實際應用時才能夠合理選型,避免因強行使用設計模式、讓程式碼更加不好維護的情況出現。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2998111/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 設計模式:代理、裝飾和介面卡模式的區別設計模式
- c#裝飾器模式詳解C#模式
- GoF設計模式中裝飾器、代理與介面卡的區別與聯絡 - MarioGo設計模式
- c++設計模式-裝飾器模式和代理模式C++設計模式
- 裝飾模式(裝飾設計模式)詳解——小馬同學@Tian設計模式
- MobX詳解(一):裝飾者模式模式
- 設計模式----裝飾器模式設計模式
- 設計模式-裝飾器模式設計模式
- [設計模式] 裝飾器模式設計模式
- 6、Python與設計模式–裝飾器模式Python設計模式
- 代理模式詳解模式
- 裝飾器模式(Decorator)模式
- 設計模式(八)裝飾器模式設計模式
- 設計模式之-裝飾器模式設計模式
- 設計模式之【裝飾器模式】設計模式
- 設計模式(六):裝飾器模式設計模式
- java設計模式--裝飾器模式Java設計模式
- 設計模式 - 代理模式詳解設計模式
- 設計模式:代理模式詳解設計模式
- 橋接模式與裝飾模式的對比橋接模式
- 《魂鬥羅歸來》之代理模式VS裝飾模式模式
- 設計模式詳解之結構型設計模式——介面卡、裝飾器設計模式
- Go 設計模式之裝飾器模式Go設計模式
- PHP設計模式- Decorator 裝飾器模式PHP設計模式
- Java設計模式系列-裝飾器模式Java設計模式
- Python設計模式-裝飾器模式Python設計模式
- Java 設計模式(五)《裝飾器模式》Java設計模式
- java設計模式之裝飾器模式Java設計模式
- java設計模式-裝飾器模式(Decorator)Java設計模式
- Java設計模式12:裝飾器模式Java設計模式
- Python裝飾器模式Python模式
- 原始碼中的設計模式--裝飾器模式原始碼設計模式
- 結構型模式之介面卡模式、橋接模式與裝飾器模式(一)模式橋接
- MySQL第七天----Connection連線池、包裝模式(裝飾模式)與動態代理模式MySql模式
- 【設計模式】-代理模式及動態代理詳解設計模式
- 設計模式 #4 (裝飾器模式、介面卡模式)設計模式
- 設計模式之裝飾器模式(decorator pattern)設計模式
- 23種設計模式(三)--裝飾器模式設計模式