设计模式 C++装饰模式

买了新房(毛坯房)需要装修,对新房进行装修并没有改变房子用于居住的本质,但它让房子变得更漂亮,更加满足居家的需求。在软件设计中,我们也可以用类似的技术对原有对象(新房)的功能进行扩展(装修),以获得更加符合用户需求的对象。这种技术在设计模式中称为装饰模式

装饰模式可以在不改变一个对象本身的基础上给对象增加额外的新行为,在现实生活中,这种情况比比皆是,如一张照片,可以不改变照片本身,给它增加一个相框,使得它具有防潮的功能,而且用户可以根据需要给它增加不同类型的相框,甚至可以在一个小相框的外面再套一个大相框

使用继承机制是给现有类添加功能的一种有效途径,通过继承一个现有类可以使得子类拥有自身方法的同时还拥有父类的方法,但是这种方法是静态的,用户不能控制增加行为的方式和时时机。例如我们要给奶茶加料,料有珍珠、椰果、葡萄干,如果使用继承我们就要把这三个类都要继承下来,此时类个数增多,且多继承本身就会存在一定的问题,使用不当会导致和预期不一样的结果

思想定义:动态地给以个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更加灵活。其别名也可以称为包装器

优点

  1. 装饰模式可以提供比继承更多的灵活性
  2. 可以通过一种动态的方式来扩展一个对象的功能
  3. 具体构建类和具体装饰类可以独立变化,在添加新的具体构建类和具体装饰类时不需要修改原有代码,符合开闭原则

缺点

  1. 使用装饰模式进行系统设计时将产生很多小对象和具体装饰类,这些小对象和装饰类的产生增加系统的复杂度,加大学习与理解的难度
  2. 装饰模式比继承更加容易出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐

适用场景

  1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  2. 需要动态地给一个对象添加功能,这些功能也可以动态地撤销

代码:给诺手添加狂徒和黑切

//抽象英雄
class AbstractHero
{
public:
	virtual void ShowStatus() = 0;
public:
	int mHp;//血量
	int mMp;//蓝量
	int mAt;//攻击力
	int mDf;//防御力
};

//具体英雄--诺手
class NuoShou : public AbstractHero
{
public:
	NuoShou()
	{
		mHp = 500;
		mMp = 200;
		mAt = 100;
		mDf = 80;
	}
	virtual void ShowStatus()
	{
		cout << "血量:" << mHp << endl;
		cout << "蓝量:" << mMp << endl;
		cout << "攻击力:" << mAt << endl;
		cout << "防御力:" << mDf << endl;
	}
};

//英雄添加装备,添加完后还是一个英雄,所以要继承 AbstractHero
class AbstractEquipment :public AbstractHero
{
public:
	AbstractEquipment(AbstractHero* hero)
	{
		this->hero = hero;
	}
	virtual void ShowStatus(){}
protected:
	AbstractHero* hero;
};

//狂徒装备
class KuangtuEquipment : public AbstractEquipment
{
public:
	KuangtuEquipment(AbstractHero* hero)
		: AbstractEquipment(hero)
	{}
	//增加额外的功能
	void AddKuangtu()
	{
		cout << "英雄购买了狂徒之后" << endl;
		this->mHp = this->hero->mHp + 1000;
		this->mMp = this->hero->mMp;
		this->mAt = this->hero->mAt;
		this->mDf = this->hero->mDf;
	}
	virtual void ShowStatus()
	{
		AddKuangtu();
		cout << "血量:" << mHp << endl;
		cout << "蓝量:" << mMp << endl;
		cout << "攻击力:" << mAt << endl;
		cout << "防御力:" << mDf << endl;
	}
};

//黑切
class HeiqieEquipment : public AbstractEquipment
{
public:
	HeiqieEquipment(AbstractHero* hero)
		: AbstractEquipment(hero)
	{}
	//增加额外的功能
	void AddHeiqie()
	{
		cout << "英雄购买了黑切之后" << endl;
		this->mHp = this->hero->mHp;
		this->mMp = this->hero->mMp;
		this->mAt = this->hero->mAt + 55;
		this->mDf = this->hero->mDf;
	}
	virtual void ShowStatus()
	{
		AddHeiqie();
		cout << "血量:" << mHp << endl;
		cout << "蓝量:" << mMp << endl;
		cout << "攻击力:" << mAt << endl;
		cout << "防御力:" << mDf << endl;
	}
};

测试:

void test()
{
	AbstractHero* hero = new NuoShou();
	cout << "英雄初始属性" << endl;
	hero->ShowStatus();
	cout << endl;

	hero = new KuangtuEquipment(hero);
	hero->ShowStatus();
	cout << endl;

	hero = new HeiqieEquipment(hero);
	hero->ShowStatus();
}

截图:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WhiteShirtI

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

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

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

打赏作者

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

抵扣说明:

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

余额充值