装饰者模式 Decorator
什么是装饰者模式:动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。
适用性:当采用类继承的方式会造成类爆炸的情况。如本文的例子中,基本饮料(被装饰者)可能有茶、水、牛奶等等、可以添加的(装饰者)有糖、果肉、珍珠等。
如果通过继承的方式,为每一种类型的奶茶设计一种类会造成类爆炸,同时也不利于后期的扩展(如又添加一种基本饮料豆浆的情况),此时通过装饰者模式可以很好的解决问题。
装饰者模式本质是一种组合的思想(不同于继承的思想),多组合少继承。利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
装饰者模式的主要组成部分:抽象被装饰者、具体被装饰者、抽象装饰者、具体装饰者。(当只有一个具体被装饰者、一个具体装饰者,其对应的抽象类可以省略)。
装饰者模式类图:
装饰者模式要点:
1 多种具体被装饰者(主体类)抽象出一个抽象被装饰类,后面通过多态,动态传递具体对象。
2 抽象装饰类继承抽象被装饰者(保持接口);要求传入被装饰者(使用父类应用、protected修饰);
3 多种具体装饰者抽象出一个抽象装饰类。
4 具体装饰者中,可以添加新方法,可以重写方法;需要使用被装饰者方法的地方用传入的被装饰者引用。
装饰者模式的基本代码:
/** * 被装饰抽象类——基本饮料 * * 作用:当具体的被装饰类有多种时,抽象提出该抽象类,用于后面实现多态。 */ public abstract class BaseDrink { public abstract int calculate(); public abstract void display(); }
/** * 具体的被装饰者类—— Water类 * 继承抽象的被装饰者类,并实现其中的抽象方法。 */ public class Water extends BaseDrink{ @Override public int calculate() { return 3; } @Override public void display() { System.out.println("water"); } }
/** * 具体的被装饰者类—— Tea类 * 继承抽象的被装饰者类,并实现其中的抽象方法。 */ public class Tea extends BaseDrink{ @Override public int calculate() { return 5; } @Override public void display() { System.out.println("Tea"); } }
/** * 抽象装饰者类——Decorator * 要点:1.抽象装饰者类中继承该抽象类以保持接口规范 * 2.包含该抽象类的引用以通过多态的方式对多种被装饰者类进行装饰。 */ public abstract class Decorator extends BaseDrink{ //继承,保持接口 protected BaseDrink bd; //引用,多态 public Decorator(BaseDrink bd) { this.bd = bd; } @Override public int calculate() { return bd.calculate(); } @Override public void display() { bd.display(); } }
/** * 装饰者类 果肉 */ public class FleshDecorator extends Decorator{ public FleshDecorator(BaseDrink bd) { super(bd); } @Override public int calculate() { return super.calculate() + 2; } @Override public void display() { super.display(); System.out.println("+ flesh"); } }
/**
* 装饰者类 糖
*/
public class SugarDecorator extends Decorator{
public SugarDecorator(BaseDrink bd) {
super(bd);
}
@Override
public int calculate() {
return super.calculate()+1;
}
@Override
public void display() {
bd.display();
System.out.println("+ sugar");
}
public void addMoreSugar(){
System.out.println("add more sugar");
}
}
/** * 测试用例 */ public class TestCase { public static void main(String[] args) { BaseDrink water = new Water(); SugarDecorator sugarWater = new SugarDecorator(water); sugarWater.addMoreSugar(); sugarWater.display(); System.out.println(sugarWater.calculate()); System.out.println("========================="); BaseDrink tea = new Tea(); FleshDecorator fleshTea = new FleshDecorator(tea); fleshTea.display(); System.out.println(fleshTea.calculate()); } }
//结果 F:deaIC-2019.1.3-jbr11.winjre64injava.exe -javaagent:F:deaIC-2019.1.3-jbr11.winlibidea_rt.jar=7425:F:deaIC-2019.1.3-jbr11.winin -Dfile.encoding=UTF-8 -classpath E:eclipse-workspacedecoratorDemooutproductiondecoratorDemo TestCase add more sugar water + sugar 4 ========================= Tea + flesh 7