1. 程式人生 > >設計模式——39、裝飾模式(Decorator)

設計模式——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();
	}
}