裝飾模式指的是在不必改變原類文件和使用繼承的情況下看疙,動態(tài)地擴展一個對象的功能。它是通過創(chuàng)建一個包裝對象辱姨,也就是裝飾來包裹真實的對象蹦漠。
UML:
特點:
- 裝飾對象和真實對象有相同的接口(Compent)。
- 裝飾對象包含一個真實對象的引用(ConcreteComponent)
- 裝飾對象接受所有來自客戶端的請求露乏。它把這些請求轉(zhuǎn)發(fā)給真實的對象碧浊。
- 裝飾對象可以在轉(zhuǎn)發(fā)這些請求以前或以后增加一些附加功能。這樣就確保了在運行時瘟仿,不用修改給定對象的結(jié)構(gòu)就可以在外部增加附加的功能
例子:
設(shè)計模型:咖啡館點咖啡
特點:咖啡品種很多箱锐,例如有原味,摩卡劳较,拿鐵驹止,卡布基諾等等,價格也不一樣观蜗。其次臊恋,咖啡也可以根據(jù)不同的口感加不同的調(diào)料,有牛奶嫂便,糖等等捞镰。最后在結(jié)賬的時候,不同的咖啡加不同的調(diào)味劑毙替,生成的價格是不同的岸售。
//裝飾者與原型共同的接口
public abstract class Drink {
//產(chǎn)品描述,可能是咖啡厂画,也可能是調(diào)味劑
public String description="";
//價格
private float price=0f;;
public void setDescription(String description){
this.description=description;
}
public String getDescription(){
return description+"-"+this.getPrice();
}
public float getPrice(){
return price;
}
public void setPrice(float price){
this.price=price;
}
//實現(xiàn)類具體實現(xiàn)價格計算
public abstract float cost();
}
//基類原型
public class Coffee extends Drink {
@Override
public float cost() {
// 獲取價格
return super.getPrice();
}
}
//實現(xiàn)的子類脫咖啡因咖啡
public class Decaf extends Coffee {
public Decaf(){
super.setDescription("Decaf");
super.setPrice(3.0f);
}
}
public class Espresso extends Coffee{
public Espresso(){
super.setDescription("Espresso");
super.setPrice(4.0f);
}
}
//包裝類凸丸,要實現(xiàn)原型相同的接口Drink(我們這里是抽象類)
public class Decorator extends Drink {
//引用原型
private Drink Obj;
//注入原型
public Decorator(Drink Obj){
this.Obj=Obj;
};
@Override
public float cost() {
// 它把計算價格的請求轉(zhuǎn)發(fā)給真實的對象,并增加一些附加功能
return super.getPrice()+Obj.cost();
}
@Override
public String getDescription(){
return super.description+"-"+super.getPrice()+"&&"+Obj.getDescription();
}
}
//具體的裝飾者 牛奶
public class Milk extends Decorator {
public Milk(Drink Obj) {
super(Obj);
super.setDescription("Milk");
super.setPrice(2.0f);
}
}
//大豆
public class Soy extends Decorator {
public Soy(Drink Obj) {
super(Obj);
super.setDescription("Soy");
super.setPrice(1.5f);
}
}
//具體的使用方式
public class CoffeeBar {
public static void main(String[] args) {
Drink order;
order=new Decaf();
System.out.println("order1 price:"+order.cost());
System.out.println("order1 desc:"+order.getDescription());
System.out.println("****************");
order=new Espresso();
order=new Milk(order);
order=new Soy(order);
order=new Milk(order);
System.out.println("order2 price:"+order.cost());
System.out.println("order2 desc:"+order.getDescription());
}
}
在設(shè)計這個模型的時候我們分析下以后可能擴展的地方有:咖啡種類袱院,調(diào)味劑種類屎慢,這兩個種類是排列組合式的搭配。
裝飾者很好的體現(xiàn)了多用組合忽洛,少用繼承腻惠,利用繼承設(shè)計子類的行為,是在編譯時靜態(tài)決定的欲虚,而且所有的子類都會繼承到相同的行為集灌。然而,如果能夠利用組合的做法擴展對象的行為复哆,就可以在運行時動態(tài)地進行擴展欣喧。