设计模式-装饰者模式

要解决的问题

考虑一个咖啡店收费的问题:如何实现灵活的咖啡的价格的计算。咖啡店主要卖咖啡,可是后来为了知足不一样客户的不一样口味,只是纯咖啡,显得太单调了,就考虑增长不一样的搭配,搭配不一样的配料后会组成另外一种饮品,这样,品种丰富了,但随之问题也来了,如何为不一样新的品种计算新的准确的价格。两种方案:编程

第一种:能够采用继承的方式,将纯咖啡做为基类,然后须要什么品种的话,能够生成一个子类继承基类,单独做为一个品种来计算价格的方法,而且还能够为这个品种添加其它功能。可是,继承有一个很大的问题就是,这样的方案实现是首先你是知道都有什么品种的,才会派生出各类子类,可是,若是后续想要在某个现有品种中去掉一些或者加上一些内容,甚至直接删掉这个品种,就会很麻烦,由于老是要去修改对应的子类;并且还有个缺点,会产生不少种子类,若是品种不少,并且每一个品种的差异很小的时候,都分别单独做为一个类就会很麻烦。ide

第二种:就是采用装饰者模式。先类比一下生活中的一个例子:一张纸质的照片,想要让这个照片保存的久一点,能够先给这张照片塑封;塑封后,以为还不够的话,可能还会给这张照片装一个相框;加一个相框还以为不能好好保护相片的话,再加个玻璃罩。在这个例子中,能够理解照片自己就是要被装饰的对象,塑封胶、相框、玻璃罩都是做为装饰者。每一层的装饰着都不会修改最里边的被装饰的对象。这里能够把具体的咖啡饮品看成被装饰者,要加入的食物或饮料看成装饰者,每一种咖啡饮品能够被不一样的装饰者装饰。测试

将上述为不一样咖啡饮品计算价格的问题用编程的概念来说就是如何透明的给一个对象增长功能。并实现功能的动态组合。这就是装饰者模式的功能。ui


模式定义

装饰者模式可以实现动态地为对象添加功能,从一个对象外部透明的给对象增长功能。透明地给一个对象增长功能,就是说要给一个对象增长功能,可是不能让这个对象知道,也就是不能去修改这个对象。this

每一个被装饰者能够被多个装饰者装饰。例如:黑咖啡(被装饰者)能够被牛奶(装饰者)、水果(装饰者)装饰,并且,不一样的装饰者之间没有前后顺序的限制。3d


具体实现

装饰者须要和被装饰者的对象继承于一样的类或者实现一样的接口,然后,在具体的装饰者实现中,转调被装饰者对象(这就须要装饰者对象持有一个被装饰者对象)。code

下边是具体实现的 UML 图和不一样类之间的调用层次图。
对象

CoffeeComponent:咖啡基类(也能够是接口)
BlackCoffee:具体的咖啡,就是被装饰的对象
CondimentDecorator:配料的基类(装饰者的基类),并且须要继承于被装饰着的基类 CoffeeComponent,同时还要持有一个 CoffeeComponent 类型的属性。
MilkDecorator:牛奶装饰者,具体的装饰者对象。blog


实例

  • 抽象组件--CoffeeComponent
/**
 * 抽象组件
 */
public abstract class CoffeeComponent {
    protected String desc;
    
    public String getDesc(){
        return desc;
    }
    
    public abstract double cost();
}
  • 具体组件--BlackCoffee(被装饰者)
/**
 * 具体组件--BlackCoffee
 * 被装饰者
 */
public class BlackCoffee extends CoffeeComponent{
    
    public BlackCoffee(){
        desc = "Black Coffee";
    }
    
    @Override
    public double cost() {
        return 10.0;
    }
}
  • 抽象装饰者--CondimentDecorator
/**
 * 抽象装饰者--CondimentDecorator
 * 须要跟被装饰者BlackCoffee同样继承抽象组件CoffeeComponent
 */
public abstract class CondimentDecorator extends CoffeeComponent{
    
    public abstract double cost();
}
  • 具体装饰者--MilkDecorator
/**
 * 具体装饰者--MilkDecorator
 * 持有抽象组件的成员变量
 */
public class MilkDecorator extends CondimentDecorator{
    private CoffeeComponent coffeeComponent;

    public MilkDecorator(CoffeeComponent coffeeComponent){
        this.coffeeComponent = coffeeComponent;
    }

    public String getDesc(){
        return coffeeComponent.getDesc() + ", milk";
    }
    
    @Override
    public double cost() {
        return coffeeComponent.cost() + 2.0;
    }
}
  • 具体装饰者--FruitDecorator
/**
 * 具体装饰者--FruitDecorator
 * 持有抽象组件的成员变量
 */
public class FruitDecorator extends CondimentDecorator{
    private CoffeeComponent coffeeComponent;

    public FruitDecorator(CoffeeComponent coffeeComponent){
        this.coffeeComponent = coffeeComponent;
    }

    public String getDesc(){
        return coffeeComponent.getDesc() + ", Fruit";
    }

    @Override
    public double cost() {
        return coffeeComponent.cost() + 3.0;
    }
}
  • 测试
public class Test {
    public static void main(String[] args) {
        CoffeeComponent coffeeComponent = new BlackCoffee();
        System.out.println(coffeeComponent.getDesc() + "," + coffeeComponent.cost());
        coffeeComponent = new MilkDecorator(coffeeComponent);
        coffeeComponent = new FruitDecorator(coffeeComponent);
        System.out.println(coffeeComponent.getDesc() + "," + coffeeComponent.cost());
    }
}
  • 输出
Black Coffee,10.0
Black Coffee, milk, Fruit,15.0
相关文章
相关标签/搜索