天天看點

設計模式-裝飾器

    裝飾者模式動态的将責任附加到對象上。若要擴充功能,裝飾者提供了比繼承更有彈性的替代方案。

    用一個咖啡的例子來展示,一杯咖啡裡面往往可以加入很多的調理(裝飾者)

1.設計兩個抽象類,一個是飲料類,還有一個是調料類

/*
 * 飲料類
 */
public abstract class Beverage {
		String description="unknow beverage";
		
		public String getDescription(){
			return description;
		}
		
		public abstract double cost();
}
           
/*
 * 調料類
 * 首先讓CondimentDecorator能夠取代Beverage,是以将CondimentDecorator擴充自Beverage類。
 */
public abstract class CondimentDecorator extends Beverage {

	public abstract String getDescription(); 

}
           

2.現在有了基類,可以開始實作具體的類,先從濃縮咖啡(Espresso)開始

/*
 * 濃縮咖啡類
 */
public class Espresso extends Beverage{

	public Espresso(){
		description="Espresso";
	}
	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return 1.99;
	}
	
}
           

3.再來實作一些調料的類,以裝飾咖啡。 重寫2個父類方法getDescription(),cost()。 擷取到被他們裝飾的飲料的資訊。

* 摩卡是一個裝飾者,是以拓展自CondimentDecorator
 */
public class Mocha extends CondimentDecorator{
	
	Beverage beverage; //用一個執行個體變量記錄飲料,也就是被裝飾者
	
	public Mocha(Beverage beverage){   //通過構造器将飲料記錄下來
		this.beverage=beverage;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription()+",Mocha";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return 0.2+beverage.cost();  //0.2是Mocha的價格
	}
	
}
           
/*
 * 另一個裝飾者:奶泡,擴充自CondimentDecorator
 */
public class Whip extends CondimentDecorator {

	Beverage beverage; //用一個執行個體變量記錄飲料,也就是被裝飾者
	
	public Whip(Beverage beverage){   //通過構造器将飲料記錄下來
		this.beverage=beverage;
	}
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return beverage.getDescription()+",Whip";
	}

	@Override
	public double cost() {
		// TODO Auto-generated method stub
		return 0.3+beverage.cost();  //0.3是Whip的價格
	}

}
           

4.接下來,來看看裝飾器是如何發揮作用的

public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Beverage beverage = new Espresso();  //先産生一杯沒有調料的Espresso
		System.out.println(beverage.getDescription()+"  money="+beverage.cost()); //
		
		Beverage beverage2 = new Espresso();
		beverage2=new Whip(new Mocha(beverage2));  //産生了一杯被Whip和Mocha裝飾的Espresso
		System.out.println(beverage2.getDescription()+"  money="+beverage2.cost());
			
	
	}
}
           

裝飾器通過層層包裹發揮了作用: new Whip(new Mocha(beverage2)),裝飾器的構造函數強迫他必須傳入一個Beverage類型的參數。

裝飾者模式的應用:Java I/O

拿io流中的inpustream舉例,也是包裹的裝飾者設計模式,用DataInputStream、BufferedInputStream裝飾了FileInputStream。

設計模式-裝飾器

再看InputStream的類圖,和之前設計的咖啡和調料的類圖基本類似。

設計模式-裝飾器

FilterInputStream類似于“調料類”,而DataInputStream、BufferedInputStream都是具體實作的“調料”,可以用他們去裝飾“一個具體的飲料”------FileInputStream,而不論是FilterInputStream還是FileInputStream,他們都共同繼承于InputStream這個父類。

繼續閱讀