结构型模式Structural Patterns之装饰模式decorator

一、3个具体类继承一个抽象类,单一责任原则各自实现抽象基类中的三个方法。

#pragma once
#include<iostream>
//业务操作
class Stream 
{
public:
	virtual void Read(int number)const = 0;
	virtual void Seek(int position)const = 0;
	virtual void Write(char data) = 0;

	virtual ~Stream() {}
};

//主体类
class FileStream : public Stream 
{
public:
	virtual void Read(int number)const override
	{
		//读文件流
		std::cout << "读文件流" << std::endl;
	}
	virtual void Seek(int position)const override
	{
		//定位文件流
	}
	virtual void Write(char data)override
	{
		//写文件流
	}
};

class NetworkStream :public Stream
{
public:
	virtual void Read(int number)const override
	{
		//读网络流
		std::cout << "读网络流" << std::endl;
	}
	virtual void Seek(int position)const override
	{
		//定位网络流
	}
	virtual void Write(char data)override
	{
		//写网络流
	}

};

class MemoryStream :public Stream 
{
public:
	virtual void Read(int number)const override
	{
		//读内存流
		std::cout << "读内存流" << std::endl;
	}
	virtual void Seek(int position)const override
	{
		//定位内存流
	}
	virtual void Write(char data) override
	{
		//写内存流
	}
};

二、1、“一“”中是常见的写法,但是如果业务类满足不了需求时,就需要增加类的功能,但是我们又不希望对原有类进行修改,此时常用decorator(装饰模式)。
2、把Stream* stream从CryptoStream、BufferedStream装饰类提出来封装成装饰类的中间类,也可以把Stream放在各个装饰类中,提取出来封装成中间类是比较标准的写法。但有不应该提取到Stream类中,因为FileStream、NetworkStream 、MemoryStream类并未用到此方法。
3、CryptoStream、BufferedStream类从类的关系上展现为is a Stream和has a Stream同时存在的,但对用户表现为is a Stream的关系,一般看到这种类绝大部分就是decorator。
4、CryptoStream、BufferedStream类的方法中通过Stream
调用FileStream、NetworkStream 、MemoryStream等类的方法以外的操作,即为装饰内容,或者说需求增加内容。

#pragma once
#include "Stream.h"

//扩展操作中间类
class DecoratorStream :
	public Stream
{
private:
	Stream* stream;

protected:
	DecoratorStream(Stream * stm) :stream(stm) 
	{
	}
	Stream* getStream()const
	{
		return stream;
	}
};

//文件流扩展操作,额外的加密操作,即为装饰内容
class CryptoStream : public DecoratorStream 
{
public:
	CryptoStream(Stream* stm) :DecoratorStream(stm) 
	{

	}
	virtual void Read(int number)const override
	{
		std::cout << "读文件流扩展操作" << std::endl;
		//额外的加密操作...
		getStream()->Read(number);//读文件流
	}
	virtual void Seek(int position)const override
	{
		//额外的加密操作...
		getStream()->Seek(position);//定位文件流
		//额外的加密操作...
	}
	virtual void Write(char data)override
	{
		//额外的加密操作...
		getStream()->Write(data);//写文件流
		//额外的加密操作...
	}
};

//内存流扩展操作,额外的加密操作,即为装饰内容
class BufferedStream : public DecoratorStream
{
public:
	BufferedStream(Stream* stm) :DecoratorStream(stm) 
	{

	}
	virtual void Read(int number)const override
	{
		std::cout << "读内存流扩展操作" << std::endl;
		//额外的加密操作...
		getStream()->Read(number);//读内存流
	}
	virtual void Seek(int position)const override
	{
		//额外的加密操作...
		getStream()->Seek(position);//定位内存流
		//额外的加密操作...
	}
	virtual void Write(char data)override
	{
		//额外的加密操作...
		getStream()->Write(data);//写内存流
		//额外的加密操作...
	}
};

四、1创建建装饰类正确,2和3创建装饰类编译和运行都能通过,但却是错误的,装饰类应该用自己对应的业务类创建。原因是getStream()->Read(number);总是动态联编到用于创建自己类的对应的方法,业务上而本应该动态联编到对应的业务类方法。

#include "Stream.h"
#include "DecoratorStream.h"

int main()
{
	//1
	Stream* s1 = new FileStream();              //普通文件流类对象
	Stream* s2 = new CryptoStream(s1);			//文件流装饰类对象
	s2->Read(1);
	
	std::cout << std::endl;

	//2
	Stream* s3 = new BufferedStream(s1);		//内存流装饰类对象,初始化为文件流类对象
	s3->Read(1);

	std::cout << std::endl;

	//3
	Stream* s4 = new BufferedStream(s2);		//内存流装饰类对象,初始化为文件流类对象
	s4->Read(1);

	//注意:2和3创建装饰类错误,装饰类应该用自己对应的业务类创建
	//原因:getStream()->Read(number);动态联编到用于创建装饰的对应的方法,而本应该动态联编到对应的业务类方法

	/*输出
	读文件流扩展操作
	读文件流

	读内存流扩展操作
	读文件流

	读内存流扩展操作
	读文件流扩展操作
	读文件流
	*/
}

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙)
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大胡子的艾娃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值