学习软件设计,向OO高手迈进!
设计模式(Design pattern)是软件开发人员在软件开发过程中面临的一般问题的解决方案。
这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
是前辈大神们留下的软件设计的"招式"或是"套路"。
动态地给一个对象添加一些额外的职责。就增加功能来说, 装饰者模式相比生成子类更为灵活。
有时我们希望给某个对象而不是整个类添加一些功能。比如有一个手机,允许你为手机添加特性,
比如增加挂件、屏幕贴膜等。一种灵活的设计方式是,将手机嵌入到另一对象中,由这个对象完成特性
的添加,我们称这个嵌入的对象为装饰。这个装饰与它所装饰的组件接口一致,因此它对使用该组件的
客户透明。
意图 | 动态地给一个对象添加一些额外的职责 |
---|---|
问题 | 有时我们希望给某个对象而不是整个类添加一些功能。 即动态的为对象添加新的功能 |
解决方案 | 采用组合而非单纯继承的方式,扩展一个对象的功能 |
实现 | 创建一个原始抽象类和要添加类上的新功能。 让具体类和装饰类分别继承自原始抽象类。 装饰类中包含原始抽象类的引用 |
装饰者模式中的角色:
下面我们使用买手机来讲解该模式:
我们在生活中去买手机,经常会有套餐的例子,比如,我们买一部手机祼机多少钱,外加一个耳机,构
成的套餐价,多少钱。外加一个保护膜,构成的另外套餐价多少钱,组合套餐呢?
这分明,是一个变化极为复杂的组合。
一、定义抽象类
Phone类:原始抽象类(Component)
class Phone {
public:
virtual int cost() = 0;
};
二、定义具体类
IPhone类:具体类(ConcreteComponent)
class IPhone : public Phone {
public:
int cost() {
return 5000;
}
};
三、定义抽象装饰类
DecoratePhone类:抽象装饰类(Decorator)
class DecoratePhone : public Phone {
public:
DecoratePhone(Phone *ph) : m_Phone(ph) {}
protected:
// 子类会用到这个成员, 所以声明为 protected
Phone *m_Phone;
};
四、定义具体装饰类
ScreenProtectorPhone类:具体装饰类(ConcreteDecoratorA)
class ScreenProtectorPhone : public DecoratePhone {
public:
ScreenProtectorPhone(Phone *ph) : DecoratePhone(ph) {}
int cost() {
return 39 + m_Phone->cost();
}
};
HeadSetPhone类:具体装饰类(ConcreteDecoratorB)
class HeadSetPhone : public DecoratePhone {
public:
HeadSetPhone(Phone *ph) : DecoratePhone(ph) {}
int cost() {
return 99 + m_Phone->cost();
}
};
五、客户端
int main(int argc, char** argv) {
// 单买手机 多少钱
IPhone apple;
cout << apple.cost() << endl;
// 手机 + 钢化膜 多少钱
ScreenProtectorPhone sp(&apple);
cout << sp.cost() << endl;
// 手机 + 钢化膜x2 多少钱
ScreenProtectorPhone sp2(&sp);
cout << sp2.cost() << endl;
// 手机 + 钢化膜 + 耳机 多少钱
HeadSetPhone hp(&sp);
cout << hp.cost() << endl;
// 手机 + 钢化膜x2 + 耳机x2 多少钱
Phone *p = new ScreenProtectorPhone(new ScreenProtectorPhone(new HeadSetPhone(new HeadSetPhone(&apple))));
cout << p->cost() << endl;
return 0;
}
执行结果
5000
5039
5078
5138
5276
当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
不能采用继承的情况主要有两类:
在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
当对象的功能要求可以动态地添加,也可以再动态地撤销时。