《Design Patterns》Decorator.積跬步系列

Decorator:裝飾者模式

先代碼

接口或抽象類:

package h.l.demo.decorator;
/**
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 接口或抽象類
 */
public interface Computer {
	// 被裝飾的行爲
	public void work();
}

子類或實現類:

package h.l.demo.decorator;
/**
 * 
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 基本功能
 */
public class BasicFuncComputer implements Computer {

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

}

裝飾類:

package h.l.demo.decorator;
/**
 * 
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 裝飾類
 */
public class ComputerDecorator implements Computer {

	/**
	 * ComputerDecorator構造方法是關鍵,當然這裏也可以手動寫setComputer方法,
	 * 只不過相應的地方需要做適當修改
	 */
	private Computer computer;

	public ComputerDecorator(Computer computer) {
		this.computer = computer;
	}
	
	@Override
	public void work() {
		if (this.computer != null) {
			this.computer.work();
		}
	}
	
	// setComputer方式實現
	/*private Computer computer;

	public void setComputer(Computer computer) {
		this.computer = computer;
	}
	
	@Override
	public void work() {
		if (this.computer != null) {
			this.computer.work();
		}
	}*/
}

裝飾類子類(兩個):

package h.l.demo.decorator;
/**
 * 
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 具體的裝飾類A,重寫裝飾的內容
 */
public class ConcreteDecoratorA extends ComputerDecorator {
	public ConcreteDecoratorA(Computer computer) {
		super(computer);
	}

	@Override
	public void work(){
		super.work();
		System.out.println("我給Computer裝飾了A功能");
	}
	
	// 對應父類的setComputer方式實現

	/*@Override
	public void work(){
		super.work();
		System.out.println("我給Computer裝飾了A功能");
	}*/
}
package h.l.demo.decorator;
/**
 * 
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 具體的裝飾類B,重寫裝飾的內容
 */
public class ConcreteDecoratorB extends ComputerDecorator {
	public ConcreteDecoratorB(Computer computer) {
		super(computer);
	}

	@Override
	public void work(){
		super.work();
		System.out.println("我給Computer裝飾了B功能");
	}
	
	// 對應父類的setComputer方式實現

	/*@Override
	public void work(){
		super.work();
		System.out.println("我給Computer裝飾了B功能");
	}*/
}

測試類:

package h.l.demo.decorator;

/**
 * 
 * @author: Is-Me-Hl
 * @date: 2020年2月14日
 * @Description: 測試
 */
public class TestMainEnter {

	public static void main(String[] args) {
		// 電腦基本功能
		BasicFuncComputer bfComputer = new BasicFuncComputer();
		bfComputer.work();
		System.out.println("-----------");
		// 基本功能基礎上,動態裝飾功能A
		ComputerDecorator conA = new ConcreteDecoratorA(bfComputer);
		conA.work();
		System.out.println("-----------");
		// 基本功能基礎上,動態裝飾功能B
		ComputerDecorator conB = new ConcreteDecoratorB(bfComputer);
		conB.work();
		System.out.println("-----------");
		// 基本功能既裝飾A。也裝飾B
		ComputerDecorator conC = new ConcreteDecoratorB(new ConcreteDecoratorA(new BasicFuncComputer()));
		conC.work();
		
		// 對應setComputer實現
		// 電腦基本功能
		/*BasicFuncComputer bfComputer = new BasicFuncComputer();
		bfComputer.work();
		System.out.println("-----------");
		// 基本功能基礎上,動態裝飾功能A
		ComputerDecorator conA = new ConcreteDecoratorA();
		conA.setComputer(bfComputer);
		conA.work();
		System.out.println("-----------");
		// 基本功能基礎上,動態裝飾功能B
		ComputerDecorator conB = new ConcreteDecoratorB();
		conB.setComputer(bfComputer);
		conB.work();
		System.out.println("-----------");
		// 基本功能既裝飾A。也裝飾B
		ComputerDecorator conC = new ConcreteDecoratorB();
		conC.setComputer(conA);
		conC.work();*/
	}

}

測試結果:
在這裏插入圖片描述

後分析

  • 個人建議:寫代碼是件幸福的事,So,do it

裝飾者模式,可以動態的添加、組合新的功能,提供了比繼承更爲靈活的對象功能擴展能力。使用場景,就是某些對象需要動態添加新功能或者組合功能的時候,可以使用到裝飾者模式。從上面代碼來講,我們有一臺電腦,用BasicFunComputer類來實現了電腦的基本功能,而後,實際上電腦可以提供的不僅僅是一些基本功能如office辦公,他還支持了上網衝浪的功能(當然這個需要繳費,弄個寬帶),以及看電視、聽音樂等等一些功能,那麼對於這些功能,並不是每一個人都需要的,所以他可以根據自己的喜好隨意組合。上述代碼寫了一個裝飾類,通過對被裝飾子類實例的包裝,以達到我們所想要的組合方式。(網上有人說,裝飾者模式是繼承的替代方案,仔細想想,也是可以這麼理解,就拿上面的例子而言,電腦有基本功能office辦公,那麼有些人希望自己的電腦再加個上網衝浪的功能,有些人說我不要上網,網費太貴,我要個單機遊戲玩玩就好,還有些人甚至說,我就想聽歌音樂,衝浪、遊戲我都沒興趣,那麼對於如此繁多的組合情況,通過繼承的方式一個個是寫對應的子類,感覺不太現實。這個時候裝飾者模式的功能組合就體現出價值了。當然這裏還要提醒的是新功能組合的先後順序在實際開發中要根據業務尤其小心組合,否則會有意想不到的尷尬~)。

其他參考:

InputStream is=System.in;
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
 
//等價於
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

其他例子:參考自《大話設計模式》
裝飾者模式章節:人物換裝。上衣有三件,褲子有四條,鞋子有五雙,帽子有六頂,人物根據不同的選擇,最後輸出人物的裝扮。功能組合問題,就可以用上裝飾者模式了


注:以上文章僅是個人總結,若有不當之處,望不吝賜教

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