设计模式装饰者模式
Posted oeleven
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式装饰者模式相关的知识,希望对你有一定的参考价值。
我们到咖啡店喝咖啡的时候,往往会根据各自的口味去选择咖啡和各种配料,比如咖啡可以选择综合、深焙、低咖啡因、浓缩,配料可以选搭牛奶、摩卡、豆浆、奶泡。这个情境下就可以使用装饰者模式,用配料对咖啡进行装饰,组合成不同的咖啡。
装饰者模式——动态的将职责附加到对象上。想要扩展功能,装饰者模式是有别于继承的另一种选择。
装饰者和被装饰者对象有相同的超类,可以用一个或多个装饰者装饰一个对象,装饰者可以在被装饰者的行为之前或之后,加上自己的行为,从而达到特定的目的。
比如咖啡和配料都继承于一个超类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; } }
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; } }
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; } }
装饰类
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(); } }
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(); } }
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(); } }
测试
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是一个抽象的装饰类。
装饰者模式给我们带来了一种新的视角,除了使用继承,装饰者模式也可以对行为进行扩展。可以用无数的装饰者包装一个组件,但是装饰者模式会导致设计中出现许多的小对象,如果过渡使用的话,会让程序变得异常复杂。
以上是关于设计模式装饰者模式的主要内容,如果未能解决你的问题,请参考以下文章