設計模式——39、裝飾模式(Decorator)
裝飾模式又叫做包裝模式(Wrapper);裝飾模式以對客戶端透明的方式擴充套件物件的功能,是繼承關係的一個替代方案;裝飾模式以對客戶透明的方式動態的給一
個物件附加上更多的責任。換言之,客戶端並不會覺得物件在裝飾前和裝飾後有什麼不同; 裝飾模式可以在不創造更多子類的情況下,將物件的功能加以擴充套件。
裝飾模式把客戶端的呼叫委派到被裝飾類。裝飾模式的關鍵在於這種擴充套件完全是透明的;裝飾模式是在不必改變原類檔案和使用繼承的情況下,動態的擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。
1、裝飾模式的juese
抽象構件角色(Component)::給出一個抽象介面,以規範準備接收附加責任的物件。(如OutputStream,InputStream)
具體構件角色(Concrete Component):定義一個將要接收附加責任的類。(如FileOutputStream,FileInputStream一般是一個節點流類)
裝飾角色(Decorator):持有一個構件(Component)物件的引用,並定義一個與抽象構件介面一致的介面(FilterInputStream或FilterOutputStream)
具體裝飾角色(Concrete Decorator):負責給構件物件“貼上”附加的責任。(如FilterInputStream、FilterOutputStream的具體子類)
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream( new FileOutputStream("text.txt")));這就是一個裝飾模式的例子。
2、裝飾模式的特點:
–裝飾物件和真實物件有相同的介面。這樣客戶端物件就可以以和真實物件相同的方式和裝飾物件互動。
–裝飾物件包含一個真實物件的引用(reference)
–裝飾物件接收所有來自客戶端的請求。它把這些請求轉發給真實的物件。
–裝飾物件可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在執行時,不用修改給定物件的結構就可以在外部增加附加的功能。在面向物件的設計中,通常是通過繼承來實現對給定類的功能擴充套件。
3、裝飾模式 VS 繼承
裝飾模式
–用來擴充套件特定物件的功能
–不需要子類
–動態
–防止由於子類而導致的複雜和混亂
–更多的靈活性
–對於一個給定的物件,同時可能有不同的裝飾物件,客戶端可以通過它的需要選擇合適的裝飾物件傳送訊息。
繼承
–用來擴充套件一類物件的功能
–需要子類
–靜態
–編譯時分派職責
–導致很多子類產生
–缺乏靈活性
4、裝飾模式舉例:
抽象構件角色(Component):
public interface Component
{
public void doSomething();
}
具體構件角色(ConcreteComponent):
public class ConcreteComponent implements Component
{
@Override
public void doSomething()
{
System.out.println("dosomething A");
}
}
裝飾角色(Decorator):
public class Decorator implements Component
{
private Component component;
public Decorator(Component component)
{
this.component = component;
}
@Override
public void doSomething()
{
component.doSomething();
}
}
具體裝飾角色(Concrete Decorator):
public class ConcreteDecorator extends Decorator
{
public ConcreteDecorator(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherthing();
}
private void doAnotherthing()
{
System.out.println("do another ");
}
}
第二個具體裝飾角色
public class ConcreteDecorator2 extends Decorator
{
public ConcreteDecorator2(Component component)
{
super(component);
}
@Override
public void doSomething()
{
super.doSomething();
this.doAnotherthing();
}
private void doAnotherthing()
{
System.out.println("do another 2");
}
}
測試客戶端
public class Client
{
public static void main(String[] args)
{
//節點流
Component component = new ConcreteComponent();
//過濾流
Component component2 = new ConcreteDecorator(component); //裝飾
//過濾流
Component component3 = new ConcreteDecorator2(component2);//裝飾
//相當於Component component3 = new ConcreteDecorator2(new ConcreteDecorator(new ConcreteComponent()))
component3.doSomething();
}
}