了解装饰模式

概述

利用一个包含行为的封装对象(封装器)把源对象装饰(封装)起来,使得其绑定新的行为。

(感觉就像是套娃)

代码示例:

举一个食物拼盘的示例

  • 拼食的公共接口(抽象构件)
public interface FoodSplicing {
    public String getFoodDesc();
    public double getPrice();
}
  • 拼饭类(基础构件)
public class RiceSplicing implements FoodSplicing {
    private String name;
    public RiceSplicing() {
        this.name = "拼饭";
    }
    @Override
    public String getFoodDesc() {
        return name;
    }
    @Override
    public double getPrice() {
        return 1.0;
    }
}
  • 拼汤粉类(基础构件)
public class RiceNoodleSoupSplicing implements FoodSplicing {
    private String name;
    public RiceSplicing() {
        this.name = "汤粉";
    }
    @Override
    public String getFoodDesc() {
        return name;
    }
    @Override
    public double getPrice() {
        return 1.5;
    }
}
  • 抽象基础装饰
public class FoodSplicingDecorator implements FoodSplicing {
    private FoodSplicing food;
    
    FoodSplicingDecorator(FoodSplicing food) {
        this.food = food;
    }
    
    @Override
    public String getFoodDesc() {
        return food.getFoodDesc();
    }
    
    @Override
    public double getPrice() {
        return food.getPrice();
    }
}
  • 拼烧鸡(装饰 -> 加强行为)
public class ChickenDecorater extends FoodSplicingDecorator {
    public ChickenDecorater(FoodSplicing food) {
        super(food);
    }
    
    @Override
    public String getFoodDesc() {
        return super() + "拼烧鸡";
    }
    
    @Override
    public double getPrice() {
        return super() + 5.0;
    }  
}
  • 拼叉烧
public class PorkDecorater extends FoodSplicingDecorator {
    public ChickenDecorater(FoodSplicing food) {
        super(food);
    }
    
    @Override
    public String getFoodDesc() {
        return super() + "拼叉烧";
    }
    
    @Override
    public double getPrice() {
        return super() + 4.5;
    }  
}
  • 拼猪大肠
public class PorkLargeIntestineDecorater extends FoodSplicingDecorator {
    public ChickenDecorater(FoodSplicing food) {
        super(food);
    }
    
    @Override
    public String getFoodDesc() {
        return super() + "拼猪大肠";
    }
    
    @Override
    public double getPrice() {
        return super() + 3.5;
    }  
}
  • 客户端demo
public class Demo {
    public static void main(String[] args) {
        //one.豪华全拼饭
        FoodSplicingDecorator one = new ChickenDecorater(
            new PorkDecorater(
                new PorkLargeIntestineDecorater(
                    new RiceSplicing())));
        System.out.println(one.getFoodDesc());
        System.out.println(one.getPrice());
        //two.拼烧鸡拼汤粉
        FoodSplicingDecorator two = new ChickenDecorater(
            new RiceNoodleSoupSplicing());
        System.out.println(two.getFoodDesc());
        System.out.println(two.getPrice());
    }
}

适用场景

  • 希望在不修改代码的情况下即可使用对象且对其新增其他的行为(对应封装器的封装)
  • 使用final关键字使得某些类的扩展有一定的限制,无法直接继承。可以使用装饰模式,封装此类。

优点

  • 可用多个封装器来组合几种行为,符合单一职责。
  • 在运行时可添加或删除对象的功能(选择封装器)
  • 无需创建新子类就可以扩展对象的行为(使用封装器)

缺点

  • 在封装器栈中已有的封装器,难以删除指定的某个封装器。

    • 在new的时候已经创建已有的封装器入栈,很难再将封装器剥离
  • 实现行为受到封装器栈的顺序影响。

    • 构造方法受到栈顺序影响,也就使得与构造方法相关的行为受到封装栈顺序影响。
  • 代码看上去不优美。

    • 初始化的时候会叠加多个封装器,代码看起来很糟糕。
posted @ 2020-08-10 21:07  Faink  阅读(124)  评论(0)    收藏  举报