一、概念 繼承的缺點:類數量爆炸、設計死板以及基類加入的新功能可能並不適用於所有的子類。 裝飾者模式:動態地將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。一言以蔽之 —— 動態擴展類的行為。 角色: 1、抽象組件(Component):給出一個抽象類 ...
一、概念
- 繼承的缺點:類數量爆炸、設計死板以及基類加入的新功能可能並不適用於所有的子類。
- 裝飾者模式:動態地將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。一言以蔽之 —— 動態擴展類的行為。
- 角色:
1、抽象組件(Component):給出一個抽象類或介面,以規範準備接收附加責任的行為。
2、具體組件(ConcreteComponent):繼承或實現抽象組件,定義一個將要接收附加責任的類。
3、抽象裝飾者(Decorator):持有一個組件(Component)對象的實例,一般從抽象組件擴展,類型是抽象類或者介面,目的是達到"類型匹配"。
4、具體裝飾者(ConcreteDecorator):繼承或實現抽象裝飾者,負責給組件對象"貼上"附加的責任。
二、Demo 實現
TOPIC:我們要定義一些飲品,並能夠向飲品中添加一些調料,比如摩卡、糖之類的,然後能夠根據添加的調料種類動態的修改飲品的價格。
1、抽象組件
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
這是一個抽象組件角色 —— 飲品抽象類,抽象方法 cost() 用來規範接收附加責任的行為。
2、具體組件
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
這是兩個具體組件角色 —— 濃縮咖啡類和混合飲料類,用來接受附加責任,也就是裝飾者具體要裝飾的類!
3、抽象裝飾者
public abstract class CondimentDecorator extends Beverage {
protected Beverage beverage;
@Override
public abstract String getDescription();
}
這是一個抽象裝飾者角色,主要的目的是為了"類型匹配",什麼是"類型匹配"呢?不多說,看看下麵的測試類就一目瞭然了!
4、具體裝飾者
現在我們想往飲品中添加摩卡,然後在飲品的價格上添加上摩卡的價格,也就是在不改變飲品類內部代碼的情況下擴展飲品類的行為 —— 用摩卡類修飾飲品類!
public class Mocha extends CondimentDecorator {
public Mocha(Beverage b) {
beverage = b;
}
@Override
public String getDescription() {
return beverage.getDescription() + "+Mocha";
}
@Override
public double cost() {
return beverage.cost() + 0.20;
}
}
5、測試
測試類能幫你對裝飾者模式有更清晰的認識!
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println("濃縮咖啡:" + beverage.getDescription() + "," + beverage.cost());
Beverage beverage1 = new HouseBlend();
// 抽象裝飾者的 "類型匹配" 如下 —— 可以用同一個實例對象接收裝飾對象,以達到類行為擴展的目的。
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
System.out.println("混合飲料+2份摩卡:" + beverage1.getDescription() + "," + beverage1.cost());
}
6、java.io 中的裝飾者模式