/***********************************************************************************************
参考博客:https://blog.csdn.net/wuzhekai1985/article/details/6672614
参考书籍:《大话设计模式》
***********************************************************************************************/
1.概念
装饰模式(Decorator):动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
这里引用参考博客的例子来详细分析说明。UML类图如下:
Phone类是定义的抽象类,可以给这些对象动态地添加职责。
NokiaPhone类、iPhone类是定义的具体的对象,也可以给这些对象添加一些职责,继承自Phone类。
DecoratorPhone类是装饰抽象类,继承自Phone类,从外类来扩展Phone类的功能,但对于Phone类来说,是无需知道Decorator的存在的。
DecoratorPhoneA类、DecoratorPhoneB类就是具体的装饰对象,起到给Phone添加职责的功能。
注意:这里NokiaPhone类、iPhone类、DecoratorPhone类都是继承于Phone类。学习模式要善于变通,如果只有一个NokiaPhone类,而没有Phone类,那么就可以写成DecoratorPhone类继承于NokiaPhone类。同理,如果只有一个DecoratorPhoneA类,那么就可以不需要写DecoratorPhone类,可以把DecoratorPhone类和DecoratorPhoneA类的职责合并到DecoratorPhoneA类中去,由DecoratorPhoneA类继承NokiaPhone类。
2.代码
//公共抽象类
class Phone
{
public:
Phone() {}
virtual ~Phone() {}
virtual void ShowDecorate() {}
};
//具体的手机类 苹果手机
class iPhone : public Phone
{
private:
string m_name; //手机名称
public:
iPhone(string name) : m_name(name) {}
~iPhone() {}
void ShowDecorate() {
cout << "iPhone" << m_name << "的装饰" << endl;
}
};
//具体的手机类 诺基亚手机
class NokiaPhone : public Phone
{
private:
string m_name;
public:
NokiaPhone(string name) : m_name(name) {}
~NokiaPhone() {}
void ShowDecorate() {
cout << "NokiaPhone" << m_name << "的装饰" << endl;
}
};
//装饰类
class DecoratorPhone : public Phone
{
private:
Phone *m_phone; //要装饰的手机 父类指针
public:
DecoratorPhone(Phone *phone) : m_phone(phone) {}
virtual void ShowDecorate() {
m_phone->ShowDecorate();
}
};
//具体的装饰类A
class DecoratorPhoneA : public DecoratorPhone
{
public:
DecoratorPhoneA(Phone *phone) : DecoratorPhone(phone) {}
void ShowDecorate() {
DecoratorPhone::ShowDecorate(); //调用父类的重写函数 DecoratorPhone::ShowDecorate()
AddDecorate(); // 增加挂件
}
private:
void AddDecorate() { //增加的装饰
cout << "增加挂件" << endl;
}
};
//具体的装饰类B
class DecoratorPhoneB : public DecoratorPhone
{
public:
DecoratorPhoneB(Phone *phone) : DecoratorPhone(phone) {}
void ShowDecorate() {
DecoratorPhone::ShowDecorate(); // 调用父类的重写函数
AddDecorate(); //屏幕贴膜
}
private:
void AddDecorate() { //增加的装饰
cout << "屏幕贴膜" << endl;
}
};
客户端代码:
int main()
{
/**** 装饰过程 ****/
Phone *Myphone = new NokiaPhone("6300"); //父类指针指向子类对象。 先调用父类的构造函数,再调用子类的构造函数:打印:Phone() NokiaPhone(string name)
Phone *dpa = new DecoratorPhoneA(Myphone); //装饰,增加挂件 Phone(), DecoratorPhone(Phone *phone), DecoratorPhoneA(Phone *phone)
Phone *dpb = new DecoratorPhoneB(dpa); //装饰,屏幕贴膜 Phone(), DecoratorPhone(Phone *phone), DecoratorPhoneB(Phone *phone)
dpb->ShowDecorate();
/**** 装饰过程 ****/
delete dpb;
delete dpa;
delete Myphone;
return 0;
}
3. 分析代码
这个代码看了半天终于看懂了,说明基础不够牢固,记录一下。我们来看看每一语句c++都做了哪些操作。
第一句:Phone *Myphone = new NokiaPhone("6300");
Myphone是一个父类指针,指向子类对象NokiaPhone。new一个子类对象,而且同时还初始化了,将6300传进去。此时,会调用子类的构造函数,又发现子类继承父类,所有会先调用父类的构造函数Phone(),再调用子类的构造函数NokiaPhone(string name)。
第二句:Phone *dpa = new DecoratorPhoneA(Myphone);
dpa是一个父类指针,指向子类对象DecoratorPhoneA。这里会调用构造函数,顺序为: Phone(), DecoratorPhone(Phone *phone), DecoratorPhoneA(Phone *phone)。
第三句:Phone *dpb = new DecoratorPhoneB(dpa);
dpb是一个父类指针,指向子类对象DecoratorPhoneB。这里会调用构造函数,顺序为:Phone(), DecoratorPhone(Phone *phone), DecoratorPhoneB(Phone *phone)。
第四句:dpb->ShowDecorate();
这句是重点。
第一个问题:ShowDecorate()是虚函数,那么会调用哪个类的重写函数呢?
由于dpb是父类指针,指向了子类对象DecoratorPhoneB,所以会调用DecoratorPhoneB的ShowDecorate()。所以会执行这一语句DecoratorPhone::ShowDecorate();
DecoratorPhone::ShowDecorate();
会执行DecoratorPhone类的ShowDecorate()
,即跳转到这一句m_phone->ShowDecorate();
,此时的m_phone=dpa
,即dpa->ShowDecorate();
那么此时会调用哪个类的ShowDecorate()呢?
由于dpa是一个父类指针,指向子类对象DecoratorPhoneA,所以会调用DecoratorPhoneA的ShowDecorate()。又跳转到这句DecoratorPhone::ShowDecorate();
,再跳转到DecoratorPhone类的ShowDecorate()。执行m_phone->ShowDecorate();
,此时的m_phone=Myphone
,即Myphone->ShowDecorate();
这里调用的是父类Phone的ShowDecorate();执行cout << m_name << "的装饰" << endl;
此时就已经追溯完了。
4.结果
所以最后的打印结果是: