設計模式-裝飾模式

裝飾模式

1)裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案
2)裝飾模式可以在不創造更多子類的情況下,將對象的功能加以擴展
3)裝飾模式把客戶端的調用委派到被裝飾類。裝飾模式的關鍵在於這種擴展完全是透明的。
4)裝飾模式是在不必改變原類文件和使用繼承的情況下,動態的擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。

裝飾模式的角色

以java的IO流來說明:
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));
1)抽象構件角色
   給出一個抽象接口,以規範準備接收附加責任的對象。如:OutputStream接口
2)具體構件角色
   定義一個將要接收附加責任的類 如:FileOutputStream節點類
3)裝飾角色
  持有一個構件(Component)對象的引用,並定義一個與抽象構件接口一致的接口
  如:FilterOutputStream
4)具體裝飾角色
  負責給構件對象“貼上”附加的責任。
  如:BufferedOutputStream等過濾類

裝飾模式的特點

1)裝飾對象和真實對象有相同的接口。這樣客戶端對象就可以以和真實對象相同的方式和裝飾對象交互。
2)裝飾對象包含一個真實對象的引用(reference)
3)裝飾對象接收所有來自客戶端的請求。它把這些請求轉發給真實的對象。
4)裝飾對象可以在轉發這些請求以前或以後增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結構就可以在外部增加附加的功能。在面向對象的設計中,通常是通過繼承來實現對給定類的功能擴展。

實例

簡單裝飾:
抽象構建角色:
public interface IWorker {
	public void doSomething();
}

裝飾角色:
public class ColourWorker implements IWorker {
	private IWorker worker;//必須持有抽象構建角色
	public ColourWorker(IWorker worker){
		this.worker = worker;
	}
	@Override
	public void doSomething() {
		System.out.println("上色前");
		this.worker.doSomething();
		System.out.println("上色後");
	}
}

public class WriteWorker  implements IWorker {
	private IWorker worker;//必須持有抽象構建角色
	public WriteWorker(IWorker worker){
		this.worker = worker;
	}
	@Override
	public void doSomething() {
		System.out.println("題字前");
		this.worker.doSomething();
		System.out.println("題字後");
	}

}

客戶端
public class Test {

	public static void main(String[] args) {
		IWorker iWorker = new WriteWorker(new ColourWorker(new BaseWoker()));
		iWorker.doSomething();
//		print
//		題字前
//		上色前
//		打卡
//		上色後
//		題字後
	}
}

java的IO模擬實例:
抽象構建角色
public interface Component {
	public void doSomething();
}

具體構建功能(個人理解其實就是一個最底層的修飾)
public class ConcreteComponent implements Component {

	@Override
	public void doSomething() {
		System.out.println("基本功能");
	}

}

裝飾角色
public class Decorator implements Component {
	private Component component;

	public Decorator(Component component) {
		this.component = component;
	}

	@Override
	public void doSomething() {
		component.doSomething();
	}

}

具體裝飾角色A
public class ConcreteDecoratorA extends Decorator {
	
	public ConcreteDecoratorA(Component component) {
		super(component);
	}

	@Override
	public void doSomething() {
		super.doSomething();
		this.doAnotherThing();
	}

	private void doAnotherThing() {
		System.out.println("功能A");
	}

}

具體裝飾角色B
public class ConcreteDecoratorB extends Decorator {
	public ConcreteDecoratorB(Component component) {
		super(component);
	}

	@Override
	public void doSomething() {
		super.doSomething();
		this.doAnotherThing();
	}

	private void doAnotherThing() {
		System.out.println("功能B");
	}

}

客戶端
public class Test {
	public static void main(String[] args) {
		// 節點流
		Component component = new ConcreteComponent();
		// 過濾流 
		Component componentA = new ConcreteDecoratorA(component);
		componentA.doSomething();
		System.out.println("------------");
		// 過濾流
		Component componentB = new ConcreteDecoratorB(componentA);
		componentB.doSomething();
		Component test = new ConcreteDecoratorA(new ConcreteDecoratorB(
				new ConcreteComponent()));
		test.doSomething();
//		基本功能
//		功能A
//		------------
//		基本功能
//		功能A
//		功能B
//		基本功能
//		功能B
//		功能A
	}

}

裝飾VS繼承

裝飾模式
–用來擴展特定對象的功能
–不需要子類
–動態
–運行時分配職責
–防止由於子類而導致的複雜和混亂
–更多的靈活性
–對於一個給定的對象,同時可能有不同的裝飾
繼承
–用來擴展一類對象的功能
–需要子類
–靜態
–編譯時分派職責
–導致很多子類產生
–缺乏靈活性




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章