1模式定義
通過包裝一個裝飾對象來動態的擴展其功能(添加功能),且又不需要改變裝飾對象的接口(即:在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能)
2應用場景
- 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
- 需要動態地給一個對象增加功能,這些功能也可以動態地被撤銷。 當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴展和維護時。
3組成部分
- 抽象組件(Component) :定義裝飾方法的規範
- 被裝飾者(ConcreteComponent) :Component的具體實現,也就是我們要裝飾的具體對象。
- 裝飾者組件(Decorator) :持有組件(Component)對象的實例引用,該類的職責就是爲了裝飾具體組件對象,定義的規範。
- 具體裝飾(ConcreteDecorator) :負責給構件對象裝飾附加的功能。
4 示例場景說明
裝飾者模式之 – inputStream
- 抽象組件(InputStream) :裝飾者模式中的超類,它只有一個抽象方法read(),子類都需要對該方法進行處理
- 被裝飾者(FileInputStream , ByteArrayInputStream , StringBufferInputStream) :擁有通用實現read()基本方法
- 裝飾者組件(FilterInputStream) :定義具體裝飾者的行爲規範,可以做統一基礎處理。
- 具體裝飾(BufferedInputStream , DataInputStream , Base64InputStream) :具體的裝飾類,擁有對流的讀操作做完成具體拓展能力。
裝飾者模式讓我們可以有不同的被裝飾者,例如FileInputStream,並且如果想使用緩衝功能那麼只需寫一下代碼 : new BufferedInputStream(new FileInputStream(new File("path")));
也可以對上面代碼再進行加工,簡單的加密處理 new Base64InputStream(new BufferedInputStream(new FileInputStream(new File(""))),0)
哪怕你突然改需求了,讀取的對象不是文件,而是文本或字符,那麼可以輕鬆的將代碼改爲 :new Base64InputStream(new BufferedInputStream(new StringBufferInputStream("str")),0)
5 示例代碼
5.1//抽象組件
public interface Component {
public void methond();
}
5.2//待裝飾者(被裝飾者)
public class ConcreteComponent implements Component {
@Override
public void methond() {
// TODO Auto-generated method stub
System.out.println("ConcreteComponent::methond");
}
}
5.3 //抽象裝飾者組件
public abstract class Decorator implements Component {
public Component mComponent;
public Decorator(Component mComponent){
this.mComponent = mComponent;
}
@Override
public void methond() {
// TODO Auto-generated method stub
mComponent.methond();
}
}
5.4.1//具體的裝飾A
public class DecoratorA extends Decorator {
public DecoratorA(Component mComponent) {
super(mComponent);
// TODO Auto-generated constructor stub
}
@Override
public void methond() {
// TODO Auto-generated method stub
methondA1();
super.methond();
methondA2();
}
public void methondA1(){
System.out.println("DecoratorA:: methondA1()");
}
public void methondA2(){
System.out.println("DecoratorA:: methondA2()");
}
}
5.4.2//具體的裝飾B
package decorate;
public class DecoratorB extends Decorator {
public DecoratorB(Component mComponent) {
super(mComponent);
// TODO Auto-generated constructor stub
}
@Override
public void methond() {
// TODO Auto-generated method stub
methondB1();
super.methond();
methondB2();
}
public void methondB1(){
System.out.println("DecoratorB::methondB1()");
}
public void methondB2(){
System.out.println("DecoratorB::methondB2()");
}
}
裝飾者特徵:一:擁有被裝飾者對象,二:透明的拓展原本的方法
5.5 //客戶測試類
public class ClientDecorate {
public static void main(String[] args) {
ConcreteComponent cc = new ConcreteComponent();
DecoratorA aa = new DecoratorA(cc);
aa.methond();
aa.methondA1();
aa.methondA2();
System.out.println("----------------------");
DecoratorB bb = new DecoratorB(cc);
bb.methond();
bb.methondB1();
bb.methondB2();
System.out.println("----------------------");
bb = new DecoratorB(aa);
bb.methond();
bb.methondB1();
}
}
結果輸出:
6 總結:
7Android源碼模式分析
Android中的ContextWrapper
待續....
- 裝飾者和被裝飾者有相同的超類(Component)。
- 你可以用一個或多個具體裝飾(ConcreteDecorator)包裝一個對象。
- 裝飾者可以在所委託被裝飾者的行爲之前與/或之後,加上自己的行爲,以達到特定的目的。(類似代理模式)
- 對象可以在任何時候被裝飾,所以可以在運行時動態地、不限量地用你喜歡的裝飾者來裝飾對象。
- Component接口可以是接口也可以是抽象類,甚至是一個普通的父類(這個強烈不推薦,普通的類作爲繼承體系的超級父類不易於維護)
- 裝飾器的抽象父類Decorator並不是必須的。
站在巨人的肩膀,參考文獻:
https://blog.csdn.net/qian520ao/article/details/82529890