什么是装饰者模式: 动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。
适用性: 当采用类继承的方式会造成类爆炸的情况。如本文的例子中,基本饮料(被装饰者)可能有茶、水、牛奶等等、可以添加的(装饰者)有糖、果肉、珍珠等。
如果通过继承的方式,为每一种类型的奶茶设计一种类会造成类爆炸,同时也不利于后期的扩展(如又添加一种基本饮料豆浆的情况),此时通过装饰者模式可以很好的解决问题。
装饰者模式本质是一种组合的思想(不同于继承的思想),多组合少继承。利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
装饰者模式的主要组成部分:抽象被装饰者、具体被装饰者、抽象装饰者、具体装饰者。(当只有一个具体被装饰者、一个具体装饰者,其对应的抽象类可以省略)。
装饰者模式类图:
装饰者模式要点:
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());
}
}
//结果
add more sugar
water
+ sugar
4
=========================
Tea
+ flesh
7