C++实现装饰器模式

前三种设计模式属于组件协作类模式,后面两篇带来另一种类型的设计模式

1. 情景与意图

  有这样一个场景,一个村庄修建房屋,每户人家装修的房子都是不一样的,比如有的带游泳池,有的带车库,有的带花园等等。如果说我们需要实现每个房子的结构,后面可能会建造更多的房子,更多的组合方式,如果采用继承的方式,需要多少个类呢?
   单独泳池房子+当杜车库房子+单独花园房子+泳池&花园+花园&车库+…………这是一个阶乘的数量。因此子类非常的多。
  这便是一个问题,在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,使得这种扩展方式缺乏灵活性; 并且随着子类的增多,各种子类的组合会导致更多子类的膨胀。
  1) 如何动态地实现对象的扩展呢?
  2)在 1 的同时避免“扩展功能的增多”带来的子类膨胀
此时我们可以采用装饰器模式来实现。装饰者模式采取组合的方式。

2. 装饰器模式

   允许向一个现有的对象添加新的功能,同时又不改变其结构。
  一般我们给对象添加新的功能可能会通过继承的方式来解决,但是呢,继承会带来的问题就是,子类越来越多且会越来越臃肿。 我们知道在七大设计原则中有一条就是【组合/聚合复用原则】。我们应该优先使用组合而不是继承,装饰器模式在这个原则表现的就很强烈,

3. 代码实现房子的装饰

下面我们用代码来看看装饰器模式:
首先我们先抽象出房子,并且实现一个具体的房子类

// 抽象的房子 
class DPAbstractHouse {
public:
	// 展示一下构造
	virtual void showStructure() = 0;
};
// 具体的一个房屋类
// .h
// 这里只是简单的实现一个房子类,实际项目中不止一个,
// 我们要面向抽象编程而不是实现编程
class DPHouse : public DPAbstractHouse {
public:
	// 展示一下构造
	virtual void showStructure();

};
// .cpp
void DPHouse::showStructure() {
	std::cout << "的房子" << std::endl;
}

下面来实现抽象的装饰器。这里可能不太好理解,先看看代码。
这里抽象的装饰器继承了抽象的房屋类,是因为我们定义接口的规范,例如showStructure()这个方法。不理解,我们继续往下走。

class DPAbstractDecorator : public DPAbstractHouse {
public:
	DPAbstractDecorator(DPAbstractHouse* house);
	virtual void showStructure();
protected:
	DPAbstractHouse* _house;
};

实现具体的装饰器:

class DPGardenDecorator :public DPAbstractDecorator {
public:
	DPGardenDecorator(DPAbstractHouse* house);
	virtual void showStructure();
};


class DPSwimmingPoolDecorator :public DPAbstractDecorator {
public:
	DPSwimmingPoolDecorator(DPAbstractHouse* house);
	virtual void showStructure();
};

class DPGarageDecorator :public DPAbstractDecorator {
public:
	DPGarageDecorator(DPAbstractHouse* house);
	virtual void showStructure();
};

// .cpp
DPGardenDecorator::DPGardenDecorator(DPAbstractHouse* house)
	:DPAbstractDecorator(house) {

}

void DPGardenDecorator::showStructure() {
	std::cout << "带花园" << std::endl;
	_house->showStructure();
}

DPSwimmingPoolDecorator::DPSwimmingPoolDecorator(DPAbstractHouse* house)
	:DPAbstractDecorator(house) {

}

void DPSwimmingPoolDecorator::showStructure() {
	std::cout << "带泳池" << std::endl;
	_house->showStructure();
}

DPGarageDecorator::DPGarageDecorator(DPAbstractHouse* house)
	:DPAbstractDecorator(house) {

}

void DPGarageDecorator::showStructure() {
	std::cout << "带车库" << std::endl;
	_house->showStructure();
}

来,我们使用一下:

int main() {
	DPHouse* house = new DPHouse();\
	// 带泳池的房子
	DPAbstractDecorator *spHouse = new DPSwimmingPoolDecorator(house);
	// spHouse->showStructure();
	// 还可以进行组合,带泳池和车库的房子
	DPAbstractDecorator* gSPHouse = new DPGarageDecorator(spHouse);
	gSPHouse->showStructure();
	return 0;
}

看到这里呢,其实你心中可能在想,这不是套娃嘛。
在这里插入图片描述

4. 总结

  在上面的例子中通过采用组合而非继承的手法, 装饰器模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
  装饰器模式的目的并非解决“多子类衍生的多继承”问题, 装饰器模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
装饰器设计模式的代码见【装饰器模式C++源码】

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值