Decorator模式:動態將職責附加到對象上,若要擴展功能,裝飾者提供了比繼承更具彈性的代替方案。
一. 基本概念:
1.設計原則:
(1) 多用組合,少用繼承。
利用繼承設計子類的行爲,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行爲。然而,如果能夠利用組合的做法擴展對象的行爲,就可以在運行時動態地進行擴展。
(2)類應設計的對擴展開放,對修改關閉。
目標是允許類容易擴展,在不修改現有代碼的情況下,就可搭配新的行爲。
開放-關閉原則,需集中在設計中最有可能改變的地方,因爲它通常會引入新的抽象層次。
2.特點:
(1) 裝飾模式中使用繼承的目的是想達到裝飾者和被裝飾對象的類型匹配,而不是獲得其行爲,行爲來自於裝飾者和基本組件。只有類型一樣了才能被多次裝飾。
(2) 裝飾者和被裝飾對象有相同的超類型。
(3) 對象可以在任何時候被裝飾,是在運行時動態的,不限量的被裝飾,比繼承更多的靈活性,可以創造出很多不同行爲的組合。
(4)裝飾者設計更加複雜性。且會出現許多小類,如果過度使用,會使程序變得很複雜。
二. 實例
不同飲料、不同調料動態地組合
1. Beverage類:飲料抽象組件
飲料的基類,可把他看爲一個接口;包括一個抽象類,和一個抽象方法,這個基類可以被裝飾者繼承裝飾。
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; //可以被裝飾者覆蓋 } public abstract double cost(); }
濃縮果汁類:飲料具體組件
具體飲料,擴展自Beverage類,加上自己的屬性。
public class Espresso extends Beverage { public Espresso() { description = "Espresso";//通過構造器設置飲料的描述,description 繼承自父類。 } public double cost() { return 1.99; } }
2. Condiment類:調料抽象組件
調料抽象基類,可把他看爲一個接口;屬於裝飾者類,要擴展自Beverage類;
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
具體裝飾者類:調料具體組件
擴展自調料基類。
public class Mocha extends CondimentDecorator { public Mocha(Beverage beverage) { this.beverage = beverage;//作爲構造器參數,讓被裝飾者記錄到實例變量中, } public String getDescription() { return beverage.getDescription() + ", Mocha"; } public double cost() { return beverage.cost() + .20; } }
3.測試類:
public class StarbuzzCoffee { public static void main(String args[]) { Beverage beverage = new Espresso();//一杯Espresso飲料,不需要調料 beverage1 = new Mocha(beverage);//帶Mocha調料的Espresso飲料 beverage2 = new Whip(beverage1);//帶Mocha和Whip調料的Espresso飲料 System.out.println(beverage2.getDescription() + " $" + String.format("%.2f", beverage2.cost())); } }
三. java I/O
java.io類就採用了裝飾者模式,