設計模式:裝飾模式(Decorator)
動態地給一個物件新增一些額外的職責。就增加功能來說,裝飾模式想必生成子類更為靈活。
裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴充套件物件的功能,是繼承關係的一個替代方案。
裝飾模式中的角色有:
1. 抽象構件角色(Component):給出一個抽象介面,以規範準備接受附加責任的物件。
2. 具體構件角色(ConcreteComponent):定義一個將要接收附加責任的類。
3. 裝飾角色(Decorator):持有一個構件(Component)物件的例項,並定義一個與抽象構件介面一致的介面。
4. 具體裝飾角色(ConcreteDecorator)
舉個簡單例子(類比《Head Fisrt》中的星巴克:吃雜糧煎餅,加個雞蛋,加根火腿,加份辣條)
1 抽象構件角色
public abstract class Pancake
{
protected String name;
public String getName()
{
return this.name;
}
public abstract BigDecimal getPrice();
}
2 具體構件角色
public class CoarsePancake extends Pancake
{
public CoarsePancake(){
this.name = "雜糧煎餅";
}
@Override
public BigDecimal getPrice()
{
return new BigDecimal(5);
}
}
3 裝飾角色
public abstract class Condiment extends Pancake
{
public abstract String getName();
public void sold()
{
System.out.println(getName()+":" +getPrice());
}
}
4 具體裝飾角色
public class Egg extends Condiment
{
private Pancake pancake;
public Egg(Pancake pancake)
{
this.pancake = pancake;
}
@Override
public String getName()
{
return pancake.getName()+",加雞蛋";
}
@Override
public BigDecimal getPrice()
{
return pancake.getPrice().add(new BigDecimal(1.5));
}
}
public class Ham extends Condiment
{
private Pancake pancake;
public Ham(Pancake pancake)
{
this.pancake = pancake;
}
@Override
public String getName()
{
return this.pancake.getName()+",加火腿";
}
@Override
public BigDecimal getPrice()
{
return pancake.getPrice().add(new BigDecimal(2));
}
}
public class Lettuce extends Condiment
{
private Pancake pancake;
public Lettuce(Pancake pancake)
{
this.pancake = pancake;
}
@Override
public String getName()
{
return this.pancake.getName()+",加生菜";
}
@Override
public BigDecimal getPrice()
{
return pancake.getPrice().add(new BigDecimal(1));
}
}
5 測試程式碼
Pancake pancake = new CoarsePancake();
Condiment egg = new Egg(pancake);
Condiment ham = new Ham(egg);
ham.sold();
Condiment lettuce = new Lettuce(ham);
lettuce.sold();
測試結果:
雜糧煎餅,加雞蛋,加火腿:8.5
雜糧煎餅,加雞蛋,加火腿,加生菜:9.5
適用場景
- 想透明並且動態地給物件增加新的職責的時候
- 給物件增加的職責,在未來存在增加或減少功能
- 用繼承擴充套件功能不太現實的情況下,應該考慮用組合的方式
優缺點
優點:
- 通過組合而非繼承的方式,實現了動態擴充套件物件的功能的能力。
- 有效避免了使用繼承的方式擴充套件物件功能而帶來的靈活性差,子類無限制擴張的問題。
- 充分利用了繼承和組合的長處和短處,在靈活性和擴充套件性之間找到完美的平衡點。
- 裝飾者和被裝飾者之間雖然都是同一型別,但是它們彼此是完全獨立並可以各自獨立任意改變的。
- 遵守大部分GRAP原則和常用設計原則,高內聚、低偶合。
缺點:
- 裝飾鏈不能過長,否則會影響效率。
- 因為所有物件都是繼承於Component,所以如果Component內部結構發生改變,則不可避免地影響所有子類(裝飾者和被裝飾者),也就是說,通過繼承建立的關係總是脆弱地,如果基類改變,勢必影響物件的內部,而通過組合建立的關係只會影響被裝飾物件的外部特徵。
- 只在必要的時候使用裝飾者模式,否則會提高程式的複雜性,增加系統維護難度。
Jdk中的裝飾模式:由於Java I/O庫需要很多效能的各種組合,如果這些效能都是用繼承的方法實現的,那麼每一種組合都需要一個類,這樣就會造成大量效能重複的類出現。而如果採用裝飾模式,那麼類的數目就會大大減少,效能的重複也可以減至最少。因此裝飾模式是Java I/O庫的基本模式。
根據上圖可以看出:
- 抽象構件(Component)角色:由InputStream扮演。這是一個抽象類,為各種子型別提供統一的介面。
- 具體構件(ConcreteComponent)角色:由ByteArrayInputStream、FileInputStream、PipedInputStream、StringBufferInputStream等類扮演。它們實現了抽象構件角色所規定的介面。
- 抽象裝飾(Decorator)角色:由FilterInputStream扮演。它實現了InputStream所規定的介面。
- 具體裝飾(ConcreteDecorator)角色:由幾個類扮演,分別是BufferedInputStream、DataInputStream以及兩個不常用到的類LineNumberInputStream、PushbackInputStream。
歡迎支援筆者新書:《RabbitMQ實戰指南》以及關注微信公眾號:Kafka技術專欄。
相關推薦
設計模式:裝飾器(Decorator)模式
讓我 分享圖片 底部 .com 一件事 輸出 PE 新的 int 設計模式:裝飾器(Decorator)模式 一、前言 裝飾器模式也是一種非常重要的模式,在Java以及程序設計中占據著重要的地位。比如Java的數據流處理,我們可能看到數據流經過不同的類的包裝和包裹,最
設計模式之裝飾者(Decorator)模式
首先來看一個場景,如圖: 工人分為很多種類,比如電工,管道工等等,同時又有A公司的電工,B公司的電工,A公司的管道工,B公司的管道工等等,那麼當有M個工種和N個公司的時候,就會有 M * N 個子類,這個繼承體系就會變得很龐大和複雜。那麼如何簡化呢,那麼
設計模式:裝飾模式(Decorator)
動態地給一個物件新增一些額外的職責。就增加功能來說,裝飾模式想必生成子類更為靈活。 裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴充套件物件的功能,是繼承關係的一個替代方案。 裝飾模式中的角色有: 1. 抽象構件角色(Com
設計模式(7)—— 結構型 —— 裝飾器(Decorator )
介紹 定義:在不改變原有物件基礎之上,將功能附加到物件上 說明:在擴充套件原有物件功能方面,提供了比繼承更有彈性的替代方案 型別:結構型 適用場景: 擴充套件一個類的功能或給一個類新增附加職責 動態地給一個
設計模式:觀察者(Observer)模式
image 強制轉換 trace vat PE sta obs observer -a 設計模式:觀察者(Observer)模式 一、前言 觀察者模式其實最好的名稱應該是“發布訂閱”模式,和我們現在大數據之中的發布訂閱方式比較類似,但是也有區別的地方,在上一個設計模式,
設計模式:享元(FlyWeight)模式
例子 清理 什麽 public == lean http 變量 -- 設計模式:享元(FlyWeight)模式 一、前言 享元(FlyWeight)模式顧名思義,既是輕量級的,原因就是享元,共享元素,這裏的元素指的是對象。如何共享對象,那就是在檢測對象產生的時候,如
C#設計模式之結構類模式:裝飾模式
負責 gzip null pattern 產生 設計師 san 抽象 接口 定義(Decorator Pattern): 動態的給一個對象添加一些額外的職責。就添加功能來說,它相比生成子類更為靈活。 一、引言 在軟件開發中,我們經常想要對一類對象添加不同的功能,例如要給手
“Head First 設計模式“ :裝飾模式
裝飾模式 裝修模式 JAVAIO裝飾模式 裝飾模式 裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。 裝修模式的角色如下:抽象構件角色(Component):給出一個抽象接口,以規範準備接收附加責任的對象。具體構件角色(Concrete Com
設計模式:裝飾模式特點、與繼承比較分析總結
目錄 一、裝飾模式簡介 二、裝飾模式的角色 三、裝飾模式編碼實現 四、裝飾模式與繼承的比較 五、裝飾模式應用場景 一、裝飾模式簡介 裝飾模式(Decorator)又名裝飾者模式模式。 什麼是裝飾模式?裝飾模式有哪些 特點? 1、動態的將責任附加到物件上,若
TypeScript學習筆記(九):裝飾器(Decorators)
標註 時裝 als cal () 操作 enume 筆記 文檔 裝飾器簡介 裝飾器(Decorators)為我們在類的聲明及成員上通過元編程語法添加標註提供了一種方式。 需要註意的是:裝飾器是一項實驗性特性,在未來的版本中可能會發生改變。 若要啟用實驗性的裝飾器特性
Python 裝飾器(Decorator)
highlight () 註冊 內部 AI 面積 return 使用 工作 裝飾器的語法為 @dec_name ,置於函數定義之前。如: import atexit @atexit.register def goodbye(): print(‘Goodbye
(轉)python裏為什麽需要使用裝飾器(decorator)
上線 深入 add 指導 對象 引用 是否 寫代碼 學習 出處 為什麽需要使用裝飾器呢?其實很多人學習python之後都會問這個問題。這一次,我來深入地學習一下什麽是裝飾器,以及為什麽需要它。其實這個裝飾器就是我們這樣的程序員太“懶”了,基本上什麽
修飾符@,裝飾器(decorator),迭代器(iterator),生成器(Generator)的一些見解
這三個方法,在Python裡的使用並不多,然而,各大網際網路公司還特別喜歡考這一方面的。以前因為不常用,有些忽視了這幾個方法,碰了幾次壁後,決心好好整理一番這三個方法(以下程式碼均在python3.6的環境下實驗):  
python黑魔法---裝飾器(decorator)
python 是一門優雅的語言,有些使用方法就像魔法一樣。裝飾器(decorator)就是一種化腐朽性為神奇的技巧。最近一直都在使用 Tornado 框架,一直還是念念不忘 Flask 。Flask 是我最喜歡的 Python 框架,最早被它吸引也是源自它使用裝飾器這個語法糖(Syntactic sugar
裝飾器(Decorator)
1. 函式也是物件 在python中,函式也是物件,它有自己的方法,它可以傳遞下去。 函式傳遞 >>> def brown(): print 'brown' >>> new_brown = brow
深入理解Python 裝飾器(decorator)
返璞歸真, 看山還是山 剛看到Python裝飾器時, 覺得很神奇。簡單實驗下,發現也就那麼回事。但是慢慢的看到越來越多的裝飾器。很多時候又不瞭解到底是怎麼回事了。 最後還是決定好好研究下。 先看看一些例項, 然後再來分析下原理 假設我們有如下
結構型模式:裝飾模式
結果 什麽 inpu 不同的 滿足 裝飾模式 ebr pro 對象 文章首發: 結構型模式:裝飾模式 七大結構型模式之四:裝飾模式。 簡介 姓名 :裝飾模式 英文名 :Decorator Pattern 價值觀 :人靠衣裝,類靠裝飾 個人介紹 : Attach add
設計模式:裝飾者模式(Decorator Pattern)
設計模式:裝飾者模式(Decorator Pattern) /** * 裝飾者模式。 * @author Bright Lee */ public class DecoratorPattern { public static void main(String[
設計模式學習筆記十五:裝飾模式(Decorator Pattern)
1.概述 將表現與邏輯分離,是應用設計的一重要原則,在WEB應用中顯得尤為重要,因為使用者對介面形式的要求是易變的,並且是非常苛刻的。如果應用邏輯與顯示糾纏在一起,就會導致對介面上既是很小的一點改動,都會牽扯到邏輯的變化。在這種情況下,我們可以繼承來擴充套件物件的功能,但是由於繼承為型別
設計模式之裝飾(Decorator)模式
isp 撤銷 有一個 inf 替代 接受 需要 裝飾著模式 () 設計模式之裝飾(Decorator)模式 (一)什麽是裝飾(Decorator)模式 裝飾模式,又稱為包裝模式,它以對客戶端透明的方式擴張對象的功能,是繼承關系的替代方案之一。 裝飾模式可以在不使用創造