天天看點

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

裝飾者模式介紹

裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。這種模式建立了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。

裝飾者模式是動态的将新功能附加到對象上。在對象功能擴充方面,它比繼承更有彈性,裝飾者模式也展現了開閉原則(ocp)。這裡提到的動态的将新功能附加到對象和ocp原則,在後面的應用執行個體上會以代碼的形式展現。

應用場景

星巴克咖啡訂單項目(咖啡館) :

1)咖啡種類/單品咖啡:Espresso(意大利濃咖啡)、ShortBlack、 LongBlack(美式咖啡)、Decaf(無因咖啡)

2)調料:Milk、 Soy(豆 漿)、Chocolate

3)要求在擴充新的咖啡種類時,具有良好的擴充性、改動友善、維護友善

4)使用00來計算不同種類咖啡的費用:客戶可以點單品咖啡,也可以單品咖啡+調料組合。

說明:該場景類似于點奶茶,我點咖啡時,可以選擇單點一份咖啡,也可以選擇向咖啡中加入調料,如牛奶、豆漿等,在結賬時需要計算咖啡的費用+調料的總費用

裝飾者模式原理

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

就以上面應用場景為例,單品咖啡是被裝飾者,裝飾者是牛奶豆漿等調料,這兩者都繼承一個抽象類(Drink),而在裝飾者(調料)中,封裝了這個抽象類(即将該抽象類寫成了成員變量)。

設計方案

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

裝飾者模式下的訂單:2份巧克力+1份牛奶的LongBlack

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

說明:

  1. Milk包含了LongBlack
  2. 一份Chocolate 包含了(Milk+LongBlack)
  3. 一份Chocolate包 含了(Chocolate+Milk+LongBlack)
  4. 這樣不管是什麼形式的單品咖啡+調料組合,通過遞歸方式可以友善的組合和維護。

具體實作

抽象類:

package com.syc.decorator;

public abstract class Drink {

	public String des; // 描述
	private float price = 0.0f;
	public String getDes() {
		return des;
	}
	public void setDes(String des) {
		this.des = des;
	}
	public float getPrice() {
		return price;
	}
	public void setPrice(float price) {
		this.price = price;
	}
	
	//計算費用的抽象方法
	//子類來實作
	public abstract float cost();
	
}
           

抽象層:

package com.syc.decorator;

public class Coffee  extends Drink {

	@Override
	public float cost() {
		return super.getPrice();
	}
}
           

美式咖啡:

package com.syc.decorator;

public class LongBlack extends Coffee {

	public LongBlack() {
		setDes(" longblack ");
		setPrice(5.0f);
	}
}
           

意大利咖啡:

package com.syc.decorator;

public class Espresso extends Coffee {
	
	public Espresso() {
		setDes("意大利咖啡 ");
		setPrice(6.0f);
	}
}
           

裝飾器類:

package com.syc.decorator;

public class Decorator extends Drink {
	private Drink obj;
	
	public Decorator(Drink obj) { //組合
		this.obj = obj;
	}
	
	@Override
	public float cost() {
		// getPrice 自己價格
		return super.getPrice() + obj.cost();
	}
	
	@Override
	public String getDes() {
		// obj.getDes() 輸出被裝飾者的資訊
		return des + " " + getPrice() + " && " + obj.getDes();
	}
}
           

調料牛奶:

package com.atguigu.decorator;

public class Milk extends Decorator {

	public Milk(Drink obj) {
		super(obj);
		setDes(" 牛奶 ");
		setPrice(2.0f); 
	}
}
           

調料豆漿:

package com.atguigu.decorator;

public class Soy extends Decorator{

	public Soy(Drink obj) {
		super(obj);
		setDes(" 豆漿  ");
		setPrice(1.5f);
	}
}
           

測試類:

package com.syc.decorator;

public class CoffeeBar {

	public static void main(String[] args) {
		// 裝飾者模式下的訂單:2份巧克力+一份牛奶的LongBlack

		// 1. 點一份 LongBlack
		Drink order = new LongBlack();
		System.out.println("費用1=" + order.cost());
		System.out.println("描述=" + order.getDes());

		// 2. order 加入一份牛奶
		order = new Milk(order);

		System.out.println("order 加入一份牛奶 費用 =" + order.cost());
		System.out.println("order 加入一份牛奶 描述 = " + order.getDes());

		// 3. order 加入一份巧克力
		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入一份巧克力  費用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入一份巧克力 描述 = " + order.getDes());

		// 3. order 加入一份巧克力
		order = new Chocolate(order);

		System.out.println("order 加入一份牛奶 加入2份巧克力   費用 =" + order.cost());
		System.out.println("order 加入一份牛奶 加入2份巧克力 描述 = " + order.getDes());
	
		System.out.println("===========================");
		
		Drink order2 = new DeCaf();
		
		System.out.println("order2 無因咖啡  費用 =" + order2.cost());
		System.out.println("order2 無因咖啡 描述 = " + order2.getDes());
		
		order2 = new Milk(order2);
		
		System.out.println("order2 無因咖啡 加入一份牛奶  費用 =" + order2.cost());
		System.out.println("order2 無因咖啡 加入一份牛奶 描述 = " + order2.getDes());
	}
}

           

輸出:

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

裝飾者模式在JDK應用的源碼分析

在JDK的源碼中,InputStream使用的就是裝飾者模式,其中InputString是抽象類(如Drink類),FilterInputStream是裝飾者(如上面的Decorator),DataInputStream是FilterInputStream的子類(如上面的Milk)

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

測試類

裝飾者設計模式裝飾者模式介紹應用場景裝飾者模式原理設計方案具體實作裝飾者模式在JDK應用的源碼分析

繼續閱讀