裝飾者模式簡述

裝飾者模式

  • 裝飾者模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作爲現有的類的一個包裝。
  • 這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
  • 我們通過下面的實例來演示裝飾者模式的用法
注意
要實現裝飾者模式,注意以下幾點內容:
a.裝飾者類要實現真實類同樣的接口
b.裝飾者類內有一個真實對象的引用(可以通過裝飾者類的構造器傳入)
c.裝飾者類對象在主類中接受請求,將請求發給真實的對象(相當於已經將引用傳遞到了裝飾類的真實對象)
d.裝飾者可以在傳入真實對象後,增加一些附加功能(因爲裝飾對象和真實對象都有同樣的方法,裝飾對象可以添加一定的操作在調用真實對象的方法,或者先調用真實對象的方法,再添加自己的方法)
e.不用繼承
示例
  • 生產饅頭的示例
  • 假設要製造添加糖和玉米麪的饅頭:
    • 需要一個正常的饅頭
    • 添加玉米麪和糖
    • 和麪,最後生產出饅頭
  • 饅頭接口
package waking.test.zs;
/**
 * 饅頭的接口
 * @author waking
 *
 */
public interface IBread {
	void prepare();//準備
	
	void kneadFlour();//和麪
	
	void steamed();//蒸麪
	
	void process();//處理
	
}
  • 正常的饅頭的生產
package waking.test.zs;
/**
 * 正常實現饅頭
 * @author waking
 *
 */
public class NormaIBread implements IBread {

	@Override
	public void prepare() {
		System.out.println("開始準備工作、、、、");
	}

	@Override
	public void kneadFlour() {
		System.out.println("開始和麪、、、、、");
	}

	@Override
	public void steamed() {
		System.out.println("開始蒸饅頭、、、、");
	}

	@Override
	public void process() {
		prepare();
		kneadFlour();
		steamed();
	}

}
  • 抽象類加工饅頭
package waking.test.zs;
/**
 * 加工饅頭抽象類
 * @author waking
 *
 */
public abstract class AbstIBread implements IBread{
	private final IBread iBread;

	public AbstIBread(IBread iBread) {
		super();
		this.iBread = iBread;
	}
	
	//重寫準備方法
	@Override
	public void prepare() {
		this.iBread.prepare();
	}
	
	//重寫和麪方法
	@Override
	public void kneadFlour() {
		this.iBread.kneadFlour();
	}
	
	//重寫蒸饅頭方法
	@Override
	public void steamed() {
		this.iBread.steamed();
	}
	
	//重寫最後處理工作
	
	@Override
	public void process() {
		prepare();
		kneadFlour();
		steamed();
	}
}
  • 添加糖
package waking.test.zs;
/**
 * 甜饅頭
 * @author waking
 *
 */
public class SweetDecorator extends AbstIBread{

	public SweetDecorator(IBread iBread) {
		super(iBread);
	}
	
	public void sweet() {
		System.out.println("加點糖、、、、");
	}
	
	//添加糖
	@Override
	public void kneadFlour() {
		this.sweet();
		super.kneadFlour();
	}
}
  • 添加玉米麪
package waking.test.zs;
/**
 * 玉米饅頭
 * @author waking
 *
 */
public class CornDecorator extends AbstIBread {

	public CornDecorator(IBread iBread) {
		super(iBread);
	}
	
	public void addCorn() {
		System.out.println("添加玉米、、、");
	}
	
	@Override
		public void kneadFlour() {
			this.addCorn();
			super.kneadFlour();
		}

}
  • 測試類
package waking.test.zs;

import org.junit.Test;

/**
 * 測試類
 * @author waking
 *
 */

public class Tests {
	
	@Test
	public void Test1() {
		System.out.println("開始裝飾饅頭、、、");
		IBread iBread = new NormaIBread();
		//添加糖
		iBread = new SweetDecorator(iBread);
		//添加玉米麪
		iBread = new CornDecorator(iBread);
		iBread.process();
		System.out.println("裝飾完畢");
	}
}

  • 結果
開始裝飾饅頭、、、
開始準備工作、、、、
添加玉米、、、
加點糖、、、、
開始和麪、、、、、
開始蒸饅頭、、、、
裝飾完畢
總結
  • 意圖:動態的給一個對象添加一些額外的職責。就增加功能來說,裝飾者模式相比子類更靈活
  • 主要解決:一般的,我們爲了擴展一個類經常使用繼承方式實現,由於繼承爲類引入靜態特徵,並且隨着擴展功能的增多,子類會很膨脹
  • 優點:裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能
  • 缺點:多層修飾比較複雜
  • 使用場景:
    • 擴展一個類的功能
    • 動態增加功能,動態撤銷
  • 注意事項:可以替代繼承
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章