Decorator(装饰模式) 结构型

一、概述

动态地给一个对象添加一些额外的职责(不重要的功能,只是偶然一次要执行) ,就增加功能来说,装饰模式比生成子类更为灵活。建造过程不稳定,按正确的顺序串联起来进行 控制。

1.结构

  1. 部件(Component)声明封装器和被封装对象的公用接口。

  2. 具体部件(Concrete Component)类是被封装对象所属的类。它定义了基础行为,但装饰类可以改变这些行为。

  3. 基础装饰(Decorator)类拥有一个指向被封装对象的引用成员变量。该变量的类型应当被声明为通用部件接口,这样它就可以引用具体的部件和装饰。装饰基类会将所有操作委派给被封装的对象。

  4. 具体装饰类(Concrete Decorators) 定义了可动态添加到部件的额外行为。具体装饰类会重写装饰基类的方法,并在调用父类方法之前或之后进行额外的行为。

在这里插入图片描述

2.适用场景

  1. 在不影响其他对象的情况下,以多态、透明的方式给单个对象添加职责。

  2. 用继承来扩展对象行为的方案难以实现或者根本不可行,可以使用该模式。

3.优缺点

优点:

  1. 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用。

  2. 单一职责原则。你可以将实现了许多不同行为的一个大类拆 分为多个较小的类。

  3. 装饰器模式完全遵守开闭原则。

缺点:

  1. 在封装器栈中删除特定封装器比较困难。

  2. 实现行为不受装饰栈顺序影响的装饰比较困难。

  3. 各层的初始化配置代码看上去可能会很糟糕。

二、实例

#include<iostream>
#include<string>
using namespace std;

// 部件: 是具体部件和装饰类的共同基类, 在C++中实现成抽象基类
class DataSource
{
public:
	virtual void writeData(string data) = 0;
};


// 具体组件提供操作的默认实现, 这些类在程序中可能会有几个变体
class FileDataSource :public DataSource {
private:
	string file_name_;
public:
	
	explicit FileDataSource(string file_name):file_name_(file_name){}

	void writeData(string data) override {
		printf("写入文件%s中: %s\n", file_name_.c_str(), data.c_str());
		return;
	}
};

/* 装饰基类和其他组件遵循相同的接口。
* 该类的主要任务是定义所有具体装饰的封装接口。
*  封装的默认实现代码中可能会包含一个保存被封装组件的成员变量
*  并且负责对其进行初始化。
*/
class DataSourceDecorator : public DataSource {
protected:
	DataSource* data_source_;
public:
	explicit DataSourceDecorator(DataSource* ds) : data_source_(ds) {}
	void writeData(string data) override {
		data_source_->writeData(data);
	}
};

// 压缩装饰器
class CompressionDecorator : public DataSourceDecorator {
public:
	DataSourceDecorator::DataSourceDecorator;
	void writeData(string data) override {
		// 1. 对传递数据进行压缩(这里仅简单实现)
		data = "已压缩(" + data + ")";
		// 2. 将压缩后数据传递给被封装对象 writeData(写入数据)方法
		data_source_->writeData(data);
		return;
	}
};



// 加密装饰器
class EncryptionDecorator : public DataSourceDecorator {
public:
	DataSourceDecorator::DataSourceDecorator;
	void writeData(string data) override {
		// 1. 对传递数据进行加密(这里仅简单实现)
		data = "已加密(" + data + ")";
		// 2. 将加密后数据传递给被封装对象 writeData(写入数据)方法
		data_source_->writeData(data);
		return;
	}
};


int main()
{
	FileDataSource* source1 = new FileDataSource("stdout");
	
	// 将明码数据写入目标文件
	source1->writeData("tomocat");
	
	// 将压缩数据写入目标文件
	CompressionDecorator* source2 = new CompressionDecorator(source1);
	source2->writeData("tomocat");
	
	// 将压缩且加密数据写入目标文件
	EncryptionDecorator* source3 = new EncryptionDecorator(source2);
	source3->writeData("tomocat");
	
	delete source1;
	delete source2;
	delete source3;

}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值