裝飾者模式:
動态地将責任附加到對象上。若要擴充功能,裝飾者提供了比繼承更有彈性的替代方案。
特點:
1、裝飾者和被裝飾對象有相同的超類型。
2、你可以用一個或多個裝飾者包裝一個對象。
3、既然裝飾者和被裝飾對象有相同的超類型,是以在任何需要原始對象(被包裝的)的場合,可以用裝飾過的對象代替它。
4、裝飾者可以再所委托被裝飾者的行為之前與/或之後,加上自己的行為,以達到特定的目的。
5、對象可以在任何時候被裝飾是以可以在運作時動态地、不限量地用你先的裝飾者來裝飾對象。
執行個體:
購買咖啡是,可以要求在其中假如各種調料,例如:豆漿、摩卡、或者奶泡,根據所加入的調料收取不同的費用。
以裝飾者模式構造:
類圖:
話不多說,直接上代碼:
public abstract class Beverage {
//描述
String description = "Unknown Beverage";
public String getDescription(){
return description;
}
//結算方法
public abstract double cost();
}
//必須讓CondimentDecorator能夠取代Beverage,是以将CondimentDecorator擴充自Beverage
public abstract class CondimentDecorator extends Beverage{
//所有調料裝飾者必須重新實作此方法
public abstract String getDescription();
}
public class Espresso extends Beverage{
public Espresso(){
//為了設定飲料的描述,我們寫了一個構造器
description = "Espresso";
}
@Override
public double cost() {
//飲料的價錢
return 1.99;
}
}
public class Mocha extends CondimentDecorator{
//要讓mocha能夠引用一個Beverage,做法如下
//1、用一個執行個體變量記錄飲料,也就是被裝飾者
Beverage beverage;
//2、想辦法讓被裝飾者被記錄到執行個體變量中,這裡的做法是:把飲料當做構造器的參數,再由構造器将此飲料記錄在執行個體變量中
public Mocha(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
// 我們希望描述不隻是描述飲料,而是完整的連調料也描述出來,是以首先利用委托的做法,得到一個描述,然後在其後加上附加的叙述
return beverage.getDescription() + ",Mocha";
}
@Override
public double cost() {
//需要計算帶mocha飲料的價錢,首先把調用委托給被裝飾對象,以計算價格,然後再加上摩卡的價錢,得到最後結果
return 0.2 + beverage.cost();
}
}
public class CoffeeTest {
//測試類
public static void main(String[] args) {
//訂一杯濃縮咖啡,不需要飲料
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" +beverage.cost());
//訂一杯濃縮咖啡,需要mocha
Beverage beverage2 = new Espresso();
beverage2 = new Mocha(beverage2);
System.out.println(beverage2.getDescription() + " $" +beverage2.cost());
}
}