天天看點

通俗詳細講解裝飾者設計模式-設計模式-結構型1、場景直入2、解決方案3、具體代碼4、升華總結5、源碼解析

目錄

1、場景直入

2、解決方案

3、具體代碼

4、升華總結

(1)裝飾者模式定義:

(2)使用場景:

(3)優點:

(4)缺點:

5、源碼解析

1、場景直入

有一個煎餅果子類,

動态需求有加一個蛋、加兩個蛋、加辣椒、加蔥、加香菜、還有加香腸火腿等等。不同的需求對應了不同的價格。

那我們如果針對每一種需求,都聲明一個煎餅果子的子類,那需要多少類?

煎餅加一個蛋類、煎餅加一個香腸類、煎餅加兩個蛋類、煎餅加兩個蛋兩個香腸類。。。學過排列組合的老師出來一下!

可以看到,單純使用繼承,在類似場景中會導緻類的數目爆炸式增長。

2、解決方案

核心是把蛋、香腸、辣椒等這些需求都單獨建立類,然後再和煎餅果子基礎類産生組合,組合後保證産生的類還得是煎餅果子類。這就像一個人穿的衣服,長裙、短裙、褲子襯衫就像人的裝飾,人始終是主體,一個人穿上漂亮的短裙還是人嗎?當然是。穿上超短褲還是人嗎?當然是。不穿呢?。。。

首先,有一個煎餅果子抽象類AbstractBatterCake

然後,再來一個裝飾抽象類AbstractDecorator,該類繼承自煎餅果子抽象類AbstractBatterCake,保證任何的裝飾之後,得到的仍然是煎餅果子類。另外,構造方法的參數也要是煎餅果子抽象類,即從哪個類的基礎上進行裝飾,這樣保證了裝飾類的連續可動态疊加。

其次,依次具體化實作裝飾抽象類AbstractDecorator。

通俗詳細講解裝飾者設計模式-設計模式-結構型1、場景直入2、解決方案3、具體代碼4、升華總結5、源碼解析

3、具體代碼

https://github.com/phs999/DesignPatterns/tree/4f98c1fc8e1ab5cbc53533305907fd24c5ca6cca/design_pattern/src/structural/decorator/v2

一定要先看關鍵的測試類:

package structural.decorator.v2;

public class Test {
	public static void main(String[] args) {
		AbstractBatterCake batterCake;
		batterCake=new BatterCake();
		batterCake=new EggDecorator(batterCake);
		batterCake=new EggDecorator(batterCake);
		batterCake=new SausageDecorator(batterCake);
		System.out.println(batterCake.getDesc()+" 銷售價格:"+batterCake.price());
	}
	
}
           

然後是抽象煎餅類:

package structural.decorator.v2;

//抽象煎餅類
public abstract class AbstractBatterCake {
	
	protected abstract String getDesc();
	
	protected abstract int price();
}
           

基本煎餅子類: 

package structural.decorator.v2;

//煎餅
public class BatterCake extends AbstractBatterCake{
	@Override
	protected String getDesc() {
		return "煎餅";
	}
	@Override
	protected int price() {
		return 8;
		
	}
}
           

裝飾抽象類: 

package structural.decorator.v2;

public abstract class AbstractDecorator extends AbstractBatterCake{
	
	private AbstractBatterCake battercake;
	
	public AbstractDecorator(AbstractBatterCake batterCake) {
		this.battercake=batterCake;
	}
	
	//public abstract void dosomthing();
	
	@Override
	protected String getDesc() {
		return this.battercake.getDesc();
	}

	@Override
	protected int price() {
		return this.battercake.price();
	}

}
           

加蛋裝飾類:

package structural.decorator.v2;
//加蛋 裝飾
public class EggDecorator extends AbstractDecorator{

	public EggDecorator(AbstractBatterCake batterCake) {
		super(batterCake);
	}

	@Override
	protected String getDesc() {
		return super.getDesc()+"加一個雞蛋";
	}

	@Override
	protected int price() {
		return super.price()+1;
	}
	
	

}
           

香腸裝飾類: 

package structural.decorator.v2;
//加香腸 裝飾
public class SausageDecorator extends AbstractDecorator{

	public SausageDecorator(AbstractBatterCake batterCake) {
		super(batterCake);
	}

	@Override
	protected String getDesc() {
		return super.getDesc()+"加一根香腸";
	}

	@Override
	protected int price() {
		// TODO Auto-generated method stub
		return super.price()+2;
	}
	
	

}
           

4、升華總結

我們從代碼中看到,在基礎的煎餅類上我們可以不斷的疊加裝飾,使之具有更加豐富的料。但是,目前的裝飾類隻是進行了對煎餅基本方法的重寫。當然,我們可以在裝飾類中新增新的方法,使得煎餅擁有更加豐富的特性。

(1)裝飾者模式定義:

在不改變原有對象的基礎之上,将功能附加到對象上。

提供了比繼承更有彈性的替代方案(擴充原有對象功能)。

(2)使用場景:

擴充一個類的功能或給一個類添加附加職責

動态的給一個類添加功能,這些功能可以再動态的撤銷。

(3)優點:

繼承的有力補充,比繼承靈活,不改變原有對象的情況下給一個對象擴充功能。

可以将多個類中重複的功能代碼單獨拿出來,實作複用,降低基礎類的複雜性。

通過使用不同的裝飾類以及這些裝飾類的排列組合,可以實作不同的效果。

符合開閉原則。

(4)缺點:

會出現更多的代碼,更多的類,增加程式複雜性。

動态裝飾時、多層裝飾時會更複雜。比如在煎餅果子的基礎上,現在又有了包子、面條等食物,這樣就會更加複雜,不過這不是設計模式本身帶來的複雜性,是業務邏輯複雜後引起的代碼複雜性。

另外,你也可以參考 裝飾者模式在坦克大戰代碼中的應用 ,文章中對裝飾者模式進行了總結,并且對實際應用中遇到的一些問題和注意事項作了介紹。

5、源碼解析

比如我們看Java IO中的BufferedReader,該類繼承自Reader抽象類,同時在該類中使用帶參構造參數Reader,傳入修飾前的類。

通俗詳細講解裝飾者設計模式-設計模式-結構型1、場景直入2、解決方案3、具體代碼4、升華總結5、源碼解析
通俗詳細講解裝飾者設計模式-設計模式-結構型1、場景直入2、解決方案3、具體代碼4、升華總結5、源碼解析

同樣,我們也可以看到BufferedInputStream與InputStream之間的關系。