【设计模式】装饰模式 C++实现

/***********************************************************************************************
参考博客: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.结果
所以最后的打印结果是:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wolves_liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值