GoF结构型模式:装饰器模式

装饰器模式(Decorator Pattern)

在软件设计中 , 如果职责划分不清晰 , 使用继承得到的结果往往是随着需求的变化 , 子类急剧的膨胀 ,同时充斥
重复的代码,这个时候的关键是划分职责。

动态(组合)地给一个对象增加一些额外的职责 . 就增加功能而言 , Decorator模式生成子类(继承)更为灵活,
(消除重复代码 & 减少子类的个数) ------《设计模式》GoF

意图:

	动态地向对象添加功能 / 职责

应用场景:

1. 子类拓展功能不可行

2. 向同一类型对象中的某个对象动态添加或删除功能 ,而不影响到其他对象

影响:

1. 动态地向对象添加 / 删除功能 , 使代码调试变得困难

类图:

在这里插入图片描述

例如:

一个流文件类作为基类:Stream

class Stream {
public:
	virtual char read(int number) = 0;
	virtual void seek(int position) = 0;
	virtual void write(char data) = 0;

	virtual ~Stream(){}
};

在Stream衍生出各种流: FileStream 、NetworkStream …

class Stream {
public:
	virtual char read(int number) = 0;
	virtual void seek(int position) = 0;
	virtual void write(char data) = 0;

	virtual ~Stream(){}
};

//主体类
class FileStream : public Stream {
public:
	virtual char read(int number) {
		//读文件
	}
	virtual void seek(int position) {
		//定位文件
	}
	virtual void write(char data) {
		//写文件
	}
};

接下来要给这些流加密 、添加缓冲等功能:

其中的Decorator是对公共部分的抽象。(Stream *stream抽象到Decorator中去)

class CryptoStream : public DecoratorStream {	//继承Sream满足read 、 seek 、 write的接口
private:
	Stream* stream;			// = new xxStream{};

public:
	//CryptoStream(Stream* stream):stream(stream){ }
	CryptoStream(Stream* stream) :DecoratorStream(stream) { }

	virtual char read(int number)  {
		//额外的加密操作...

		stream->read(number);//读文件
	}
	virtual void seek(int position) {
		//额外的加密操作...

		stream->seek(position);//定位文件
	}
	virtual void write(char data) {
		//额外的加密操作...

		stream->write(data);//写文件
	}

};

class BufferedStream : public DecoratorStream {		//继承Stream实现接口
private:
	Stream* stream;			// = new xxStream{};

public:
	virtual char read(int number) {
		//额外的缓冲操作...

		stream->read(number);//读文件
	}
	virtual void seek(int position) {
		//额外的缓冲操作...

		stream->seek(position);//定位文件
	}
	virtual void write(char data) {
		//额外的缓冲操作...

		stream->write(data);//写文件
	}
};

Decorator的类: 其中继承Stream是为了实现其 read 、write的接口 。组合是为了去实现传进来的各种Stream的read、write的读写操作 (此处一定要明白)

class DecoratorStream : public Stream {
protected:
	Stream* stream;
	DecoratorStream() = default;
	DecoratorStream(Stream* stream) :stream(stream) {}
};

运行实例:

void process() {

	//运行时装配
	FileStream* s1 = new FileStream();	    //创建文本对象
	CryptoStream* s2 = new CryptoStream(s1);	//对文件s1进行加密
	BufferedStream{};
};

总结:

  1. 采用组合而非继承的手法 , Decorator模式实现了在运行时动态拓展的能力,
    而且可以更具需要拓展多个功能 。 避免了使用继承带来的“灵活性差” 和 “多个子类衍生问题”

  2. Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类具有的
    接口。但在实现上又表现为has-a Component的组合关系 。 Decorator类又使用了另外一个Component的类

  3. Decorator模式的目的并非解决"多子类衍生的多继承"问题,
    Decorator模式应用的要点在于解决 “主体类在多个方向上的拓展功能”----是为“装饰”的含义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值