「软件工程-设计模式」 装饰器模式

Posted by Dawn-K's Blog on February 22, 2021

装饰器模式

概述

装饰器模式主要是在不更改原有类的情况下为其增加功能. 也就是用其他类(装饰器)包含原有类的方式.

实现

比如我们有一个咖啡接口, 和一个已经实现的咖啡实体类. 我们后续想往咖啡中自由添加调料, 而不改变 SimpleCoffee 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Coffee {
    /** 获取价格 */
    double getCost();
    /** 获取配料 */
    String getIngredients();
}
class SimpleCoffee implements Coffee {

    @Override
    public double getCost() {
        return 1;
    }

    @Override
    public String getIngredients() {
        return "Coffee";
    }
}

我们令咖啡装饰器也继承 Coffee 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
abstract class CoffeeDecorator implements Coffee {
    protected final Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        decoratedCoffee = coffee;
    }

    /**
     * 装饰器父类中直接转发"请求"至引用对象,也就是做简单的封装,维持原有对象的接口
     */
    public double getCost() {
        return decoratedCoffee.getCost();
    }

    public String getIngredients() {
        return decoratedCoffee.getIngredients();
    }
}

我们根据这个装饰器类再创建实体类. 其中的价格计算都是链式调用, 一层一层向内调用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class WithMilk extends CoffeeDecorator {

    public WithMilk(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        double additionalCost = 0.5;
        return super.getCost() + additionalCost;
    }

    @Override
    public String getIngredients() {
        String additionalIngredient = "milk";
        return super.getIngredients() + ", " + additionalIngredient;
    }
}
class WithSugar extends CoffeeDecorator {

    public WithSugar(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double getCost() {
        return super.getCost() + 1;
    }

    @Override
    public String getIngredients() {
        return super.getIngredients() + ", Sugar";
    }
}

最后客户端调用的方法如下.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Coffee c = new SimpleCoffee();
print(c);

//增加牛奶的咖啡
c = new WithMilk(c);
print(c);

//再加一点糖
c = new WithSugar(c);
print(c);

/*
花费了: 1.0
配料: Coffee
============
花费了: 1.5
配料: Coffee, milk
============
花费了: 2.5
配料: Coffee, milk, Sugar
============
*/