6. 设计模式——装饰器模式

485 阅读2分钟

1. 为什么要有装饰器模式

假设有一个蛋糕店,店里有一种奶油蛋糕,售价100块。但是,通常顾客会有各种其他的需求,比如加草莓,加蓝莓等等,这时我们怎么办呢?你也许会说,可以多做几种类型的蛋糕,不就满足需求了,但是如果哪天又有新的客人有新的需求,按照这种方式我们要提供多少种分别计价呢,老板会不会疯掉呢。

这种单纯的设置新的种类像不像通过继承实现新的子类呢,光实现这些子类就会是一项很大的开发工作量,如果以后出现维护问题,那简直就是灾难。

这时我们是不是可以通过别的方法,以奶油蛋糕为主体,其他草莓,蓝莓类的材料作为装饰单独计价,这样每次顾客有新需求,只需在蛋糕的基础上加上材料的价格即可:

2. 装饰器模式UML图

2.1 角色

  1. Component:统一接口,也是装饰类和被装饰类的基本类型。
  2. ConcreteComponent:具体实现类,也是被装饰类,他本身是一个具有一定功能的完整的类。
  3. Decorator: 实现了Component接口的同时还在内部维护了ConcreteComponent的实例,并可以通过构造函数初始化,而Decorator本身,通常采用默认实现,他的存在仅仅是一个生命,要生产出一些用于装饰的子类,而其子类才是富有装饰效果的装饰产品类。
  4. ConcreteDecorator:具体的装饰产品类,每一种装饰产品具有特定的装饰效果,可以通过构造器生命装饰那种类型的ConcreteComponent,从而对其进行装饰。

3. 代码实战

先定一个Cake(Component)

public abstract class Cake {
    public abstract int cost();
}

实现Cake,做一个奶油蛋糕

public class CreamCake extends Cake {
    @Override
    public int cost() {
        return 100;
    }
}

定义一个装饰器接口

public abstract class Decorator extends Cake {

    private Cake cake = null;
    public Decorator(Cake cake) {
        this.cake = cake;
    }

    @Override
    public int cost() {
        return this.cake.cost();
    }
}

加草莓

public class StrawberryCake extends Decorator {
    public StrawberryCake(Cake cake) {
        super(cake);
    }

    @Override
    public int cost() {
        return super.cost() + 20;
    }
}

加蓝莓

public class BlueberryCake extends Decorator {
    public BlueberryCake(Cake cake) {
        super(cake);
    }

    @Override
    public int cost() {
        return super.cost() + 10;
    }
}

测试

public class Demo {
    public static void main(String[] args) {
        // 做一个奶油蛋糕
        Cake cake = new CreamCake();
        // 加草莓
        cake = new StrawberryCake(cake);
        // 加蓝莓
        cake = new BlueberryCake(cake);
        System.out.println(cake.cost());
    }
}

输出

130