裝飾器模式
它允許你在不改變對象結構的情況下,動態地將新功能附加到對象上。
結構:
- 抽象組件(Component):定義了原始對象和裝飾器對象的公共接口或抽象類,可以是具體組件類的父類或接口。
- 具體組件(Concrete Component):是被裝飾的原始對象,它定義了需要添加新功能的對象。
- 抽象裝飾器(Decorator):繼承自抽象組件,它包含了一個抽象組件對象,并定義了與抽象組件相同的接口,同時可以通過組合方式持有其他裝飾器對象。
- 具體裝飾器(Concrete Decorator):實現了抽象裝飾器的接口,負責向抽象組件添加新的功能。具體裝飾器通常會在調用原始對象的方法之前或之后執行自己的操作。
圖例:
平常假如要加一個配料,都需要修改餐品的源代碼,但是隨著配料的增多, 類會變得越來越龐大,等下類爆炸了。
public class Main {public static void main(String[] args) {FriedNoodles friedNoodles = new FriedNoodles();friedNoodles.addBacon();friedNoodles.addEgg();friedNoodles.addFish();System.out.println("Cost: $" + friedNoodles.getCost());}
}
案例:
假設有一個簡單的咖啡店系統,其中有一個 Coffee
接口表示咖啡,它有一個方法 getCost()
來獲取咖啡的價格。現在我們要給咖啡添加一些額外的配料,比如牛奶、摩卡和奶泡。
// 咖啡接口
interface Coffee {double getCost();
}// 具體咖啡類
class SimpleCoffee implements Coffee {@Overridepublic double getCost() {return 1.0;}
}// 裝飾者抽象類
abstract class CoffeeDecorator implements Coffee {protected final Coffee decoratedCoffee;public CoffeeDecorator(Coffee decoratedCoffee) {this.decoratedCoffee = decoratedCoffee;}public double getCost() {return decoratedCoffee.getCost();}
}// 具體裝飾者類
class Milk extends CoffeeDecorator {public Milk(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic double getCost() {return super.getCost() + 0.5;}
}class Mocha extends CoffeeDecorator {public Mocha(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic double getCost() {return super.getCost() + 1.0;}
}class Foam extends CoffeeDecorator {public Foam(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic double getCost() {return super.getCost() + 0.3;}
}// 使用示例
public class Main {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();coffee = new Milk(coffee);coffee = new Mocha(coffee);coffee = new Foam(coffee);System.out.println("Cost: $" + coffee.getCost());}
}
通過組合不同的裝飾者,可以在不改變原有咖啡對象的情況下,動態地添加額外的功能和費用。
使用場景:
- 動態地給對象添加功能:當需要給對象動態地添加一些額外的功能,而且這些功能可以獨立于該對象的創建。
-
當不能采用繼承的方式對系統進行擴充或者采用繼承不利于系統擴展和維護時。
不能采用繼承的情況主要有兩類:
- 第一類是系統中存在大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長;
- 第二類是因為類定義不能繼承(如final類)