装饰模式
想想一下,我现在如果想在冰淇淋里面加坚果、葡萄干怎么办?
# 场景分析
当然我们可以在多建几个工厂,穷举每一个类型。
但是也许你也发现了!
我们要的冰淇淋发生了变化,用户其实可以加更多的东西,或者随意搭配。
难道我们还能不断穷举?
即使我们可以,这种穷举也会随着添加种类,枚举的可能性不断增加,工作量是指数级增长的。
装饰器模式是怎么解决这个问题的?
装饰器其实是将每种变化封装为一种装饰,可以这直接附加到原对象上,产生一个新对象。用于解决问题。
如加两次装饰器的小明:【小明】 --到--> 【穿裤子的小明】 --到--> 【穿裤子的戴帽子的小明】
这样装饰器可以自由组合叠加。
装饰模式是给一个现有对象添加新功能,同时有不去改变其结构的方式。它可以动态的给对象增加新的功能。
# 实现
# 类图
# 代码
基础类:
class StrawberryIceCreamImpl : public IceCreamInterface
{
public:
virtual void taste() override
{
cout << "草莓味冰淇淋" << endl;
}
};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
装饰者基类:
class IceCreamDecorator : public IceCreamInterface
{
public:
IceCreamDecorator(IceCreamInterface *iceCream)
: m_pIceCream(iceCream)
{
}
virtual ~IceCreamDecorator()
{
delete m_pIceCream;
}
virtual void taste() override
{
if (m_pIceCream)
{
m_pIceCream->taste();
}
}
private:
IceCreamInterface *m_pIceCream;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
装饰者:
class NutIceCreamDecorator : public IceCreamDecorator
{
public:
NutIceCreamDecorator(IceCreamInterface *iceCream)
: IceCreamDecorator(iceCream)
{
}
virtual void taste() override
{
std::cout << "带坚果的";
IceCreamDecorator::taste();
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
客户使用:
int main()
{
StrawberryIceCreamImpl().taste();
NutIceCreamDecorator(new StrawberryIceCreamImpl()).taste();
return 0;
}
1
2
3
4
5
6
2
3
4
5
6
# 代码路径
设计模式/Decorator (opens new window)
# 使用感悟
使用场景:
不想增加子类(或者需要增加子类的数量比较多)时,想扩展类能力。
优点:
装饰类和被装饰类可以独立发展,而不会相互耦合。
有效的分割核心职责和非核心职责
可动态地扩展一个实现类的功能(【套娃】使用),减少了类的数量
注意点:
装饰模式一般是构造函数中传入被装饰的对象。
装饰模式是的目的是为了给现有对象增强能力,但是不管怎么增强,不会改变对象的本质。(这点很重要,后面会在代理中做比较)
缺点:
多层包装的装饰类,出BUG,要一层一层查。如:游戏角色的装扮,如果一共20层装饰者,工作量大。
编辑 (opens new window)
上次更新: 2023/04/09, 11:59:04