設計模式(3)裝飾者模式
阿新 • • 發佈:2019-02-22
number 設計模式 bsp bubuko override closed des ase spa
我們到咖啡店喝咖啡的時候,往往會根據各自的口味去選擇咖啡和各種配料,比如咖啡可以選擇綜合、深焙、低咖啡因、濃縮,配料可以選搭牛奶、摩卡、豆漿、奶泡。這個情境下就可以使用裝飾者模式,用配料對咖啡進行裝飾,組合成不同的咖啡。
裝飾者模式——動態的將職責附加到對象上。想要擴展功能,裝飾者模式是有別於繼承的另一種選擇。
裝飾者和被裝飾者對象有相同的超類,可以用一個或多個裝飾者裝飾一個對象,裝飾者可以在被裝飾者的行為之前或之後,加上自己的行為,從而達到特定的目的。
比如咖啡和配料都繼承於一個超類Beverage,首先最底層是一個咖啡對象,然後一層層的用配料去裝飾咖啡對象,最終得到了一個被裝飾完成的對象。
下面看下代碼
裝飾者和被裝飾在的超類
public abstract class Beverage { /** * 大小 */ private SizeEnum size; /** * 描述 * * @return 描述 */ public abstract String getDescription(); /** * 花費 * * @return 花費 */ public abstract double cost(); public SizeEnum getSize() {return size; } public void setSize(SizeEnum size) { this.size = size; } }
裝飾者的父類
public class CondimentDecorator extends Beverage{ @Override public String getDescription() { return null; } @Override public double cost() { return 0; } }
杯子大小的枚舉
public enum SizeEnum { /** * 小杯 */ TALL(1, "小杯"), /** * 中杯 */ GRANDE(2, "中杯"), /** * 大杯 */ VENTI(3, "大杯"); SizeEnum(int value, String caption) { this.value = value; this.caption = caption; } /** * 大小 */ private int value; /** * 描述 */ private String caption; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public String getCaption() { return caption; } public void setCaption(String caption) { this.caption = caption; } }
幾個繼承了超類的咖啡類
public class DarkRoast extends Beverage { public DarkRoast(SizeEnum sizeEnum) { super.setSize(sizeEnum); } @Override public String getDescription() { return "DarkRoast"; } @Override public double cost() { return 0.99; } }
public class Decaf extends Beverage { public Decaf(SizeEnum sizeEnum) { super.setSize(sizeEnum); } @Override public String getDescription() { return "Decaf"; } @Override public double cost() { return 1.05; } }Decof
public class Espresso extends Beverage { public Espresso(SizeEnum sizeEnum) { super.setSize(sizeEnum); } @Override public String getDescription() { return "Espresso"; } @Override public double cost() { return 1.99; } }Espresso
public class HouseBland extends Beverage { public HouseBland(SizeEnum sizeEnum) { super.setSize(sizeEnum); } @Override public String getDescription() { return "HouseBland"; } @Override public double cost() { return 0.89; } }HouseBland
裝飾類
public class Milk extends CondimentDecorator { private Beverage beverage; public Milk(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return "Milk, " + beverage.getDescription(); } @Override public double cost() { return beverage.cost() + 0.10; } @Override public SizeEnum getSize() { return beverage.getSize(); } }
public class Mocha extends CondimentDecorator { private Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return "Mocha, " + beverage.getDescription(); } @Override public double cost() { return beverage.cost() + 0.20; } @Override public SizeEnum getSize() { return beverage.getSize(); } }Mocha
public class Soy extends CondimentDecorator { private Beverage beverage; public Soy(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return "Soy, " + beverage.getDescription(); } @Override public double cost() { switch (this.getSize()) { case TALL: return beverage.cost() + 0.10; case VENTI: return beverage.cost() + 0.15; case GRANDE: return beverage.cost() + 0.20; default: return beverage.cost() + 0.10; } } @Override public SizeEnum getSize() { return beverage.getSize(); } }Soy
public class Whip extends CondimentDecorator { private Beverage beverage; public Whip(Beverage beverage) { this.beverage = beverage; } @Override public String getDescription() { return "Whip, " + beverage.getDescription(); } @Override public double cost() { return beverage.cost() + 0.10; } @Override public SizeEnum getSize() { return beverage.getSize(); } }Whip
測試
public static void main(String[] args) { Beverage beverage1 = new Espresso(SizeEnum.GRANDE); System.out.println(beverage1.getSize().getCaption() + " " + beverage1.getDescription() + " cost: " + beverage1.cost()); Beverage beverage2 = new DarkRoast(SizeEnum.VENTI); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Milk(beverage2); System.out.println(beverage2.getSize().getCaption() + " " + beverage2.getDescription() + " cost: " + beverage2.cost()); }
輸出
裝飾者模式的運用有很多,例如Java I/O 中 BufferedInputStream, LineNumberInputStream擴展自FileInputStream,而FileInputStream是一個抽象的裝飾類。
裝飾者模式給我們帶來了一種新的視角,除了使用繼承,裝飾者模式也可以對行為進行擴展。可以用無數的裝飾者包裝一個組件,但是裝飾者模式會導致設計中出現許多的小對象,如果過渡使用的話,會讓程序變得異常復雜。
設計模式(3)裝飾者模式