概述
裝飾器模式一種動(dòng)態(tài)地往一個(gè)類中添加新的行為的設(shè)計(jì)模式涯肩。就功能而言顷牌,修飾模式相比生成子類更為靈活,這樣可以給某個(gè)對(duì)象而不是整個(gè)類添加一些功能敢朱。
一般來說,我們想給某個(gè)類或者對(duì)象添加行為有兩種方式:繼承方式摩瞎,組合方式拴签。裝飾器模式使用的是組合方式。
實(shí)現(xiàn)
首先看下裝飾器模式的UML圖
DecoratorUML.png
可以看到旗们,裝飾器模式主要有
- 抽象被裝飾組件
- 具體被裝飾組件
- 抽象裝飾類
- 具體裝飾類
下面我將以煎餅的代碼為例子蚓哩,演示裝飾器模式
/**
* 抽象組件:煎餅
*/
public interface JianBing {
JianBing make();
}
/**
* 具體組件:楊氏煎餅
*/
public class YangShiJianBing implements JianBing {
public JianBing make() {
System.out.println("楊式煎餅");
return this;
}
}
/**
* 抽象裝飾器:調(diào)料
*/
public AbstractClass TiaoLiao implements JianBing{
protected JianBing jianbing;
public TiaoLiao(JianBing jianbing) {
this.jianbing = jianbing;
}
public JianBing make() {
jianbing.make();
}
}
/**
* 具體裝飾器:加孜然
*/
public class AddZiRan extends TiaoLiao {
public AddZiRan (JianBing jianbing) {
super(jianbing);
}
public JianBing make() {
jianbing.make();
addZiRan(jianbing);
}
public void addZiRan(JianBing jianbing) {
System.out.println(" 加孜然 ");
}
}
/**
* 具體裝飾器:加辣
*/
public class AddPepper extends TiaoLiao {
public AddPepper (JianBing jianbing) {
super(jianbing);
}
public JianBing make() {
jianbing.make();
addPepper(jianbing);
}
public void addPepper(JianBing jianbing) {
System.out.println(" 加辣 ");
}
}
/**
* 客戶
**/
public class Client {
public static void main(String[] args) {
// 煎餅 加孜然 加辣
JianBing jianbing = new YangShiJianBing();
JianBing jianBingAddPepper = new AddPepper(jianbing);
JianBing jianBingAddZiRan = new AddZiRan(jianBingAddPepper);
jianBingAddZiRan.make();
}
}
可以看到,使用了裝飾器模式之后上渴,我們可以動(dòng)態(tài)(甚至遞歸)地給組件(煎餅)添加需要的行為(調(diào)料)岸梨,很棒。這和代理模式有本質(zhì)的區(qū)別稠氮。
裝飾器模式的實(shí)例
一個(gè)比較著名的例子是Java的I/O標(biāo)準(zhǔn)庫(kù)的設(shè)計(jì)曹阔,其部分如下所示
JavaIOStreamUML.png
根據(jù)上圖可以看出:
- 抽象構(gòu)建角色(Component):由InputStream扮演。這是一個(gè)抽象類隔披,為各種子類型提供統(tǒng)一的接口赃份。
- 具體構(gòu)件角色(ConcreteComponent):由ByteArrayInputStream、FileInputStream奢米、StringBufferInputStream等類扮演抓韩。它們實(shí)現(xiàn)了抽象構(gòu)件角色所規(guī)定的接口纠永。
- 抽象裝飾角色(Decorator):由FilterInputStream、ObectInputStream等類扮演园蝠。它們實(shí)現(xiàn)了InputStream所規(guī)定的接口渺蒿。
- 具體裝飾角色(ConcreteDecorator):由幾個(gè)類扮演,分別是BufferedInputStream彪薛、DataInputStream以及兩個(gè)不常用到的類LineNumberInputStream茂装、PushbackInputStream。
裝飾器模式的優(yōu)點(diǎn)
裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能善延,但是裝飾模式可以提供比繼承更多的靈活性少态。通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合易遣”似蓿可以使用多個(gè)具體裝飾類來裝飾同一對(duì)象,得到功能更為強(qiáng)大的對(duì)象豆茫。
裝飾器模式的缺點(diǎn)
這種比繼承更加靈活機(jī)動(dòng)的特性侨歉,也同時(shí)意味著裝飾模式比繼承更加易于出錯(cuò),排錯(cuò)也很困難揩魂,對(duì)于多次裝飾的對(duì)象幽邓,調(diào)試時(shí)尋找錯(cuò)誤可能需要逐級(jí)排查,較為煩瑣火脉。