关注小程序 找一找教程网-随时随地学编程

C/C++教程

设计模式第六讲--装饰模式 Decorator

1. “单一职责”模式

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

 

典型模式

Decorator

Bridge

 

2. 动机(Motivation)

在某些情况下我们可能会“过度的使用继承来扩展对象的功能”,由于继承为类型引入的静态特质(没有变化的可能性),使得这种扩展方式缺乏灵活性;并且随着子类增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。

 

如何使“对象功能的扩展”能够根据需求来动态的实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降为最低。

 

3.代码

//业务操作
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)
	{
		//写文件流
	}
};

class NetworkStream : public Stream
{
public:
	virtual char Read(int number)
	{
		//读网络流
	}

	virtual void Seek(int position)
	{
		//定位网络流
	}

	virtual void Write(char data)
	{
		//写网络流
	}
};

class MemoryStream :public Stream
{
public:
	virtual char Read(int number)
	{
		//读内存流
	}

	virtual void Seek(int position)
	{
		//定位内存流
	}

	virtual void Write(char data)
	{
		//写内存流
	}
};

//扩展操作
class CrytoFileStream :public FileStream
{
public:
	virtual char Read(int number)
	{
		//额外的加密操作。。。
		FileStream::Read(number);  //读文件流
	}

	virtual void Seek(int position)
	{
		//额外的加密操作。。。
		FileStream::Seek(position); //定位文件流
	}

	virtual void Write(char data)
	{
		//额外的加密操作。。。
		FileStream::Write(data);//写文件流
	}
};

//扩展操作
class CrytoNetworkStream :public NetworkStream
{
public:
	virtual char Read(int number)
	{
		//额外的加密操作。。。
		NetworkStream::Read(number);  //读网络流
	}

	virtual void Seek(int position)
	{
		//额外的加密操作。。。
		NetworkStream::Seek(position); //定位网络流
	}

	virtual void Write(char data)
	{
		//额外的加密操作。。。
		NetworkStream::Write(data);//写网络流
	}
};

//扩展操作
class CrytoMemoryStream :public MemoryStream
{
public:
	virtual char Read(int number)
	{
		//额外的加密操作。。。
		MemoryStream::Read(number);  //读内存流
	}

	virtual void Seek(int position)
	{
		//额外的加密操作。。。
		MemoryStream::Seek(position); //定位内存流
	}

	virtual void Write(char data)
	{
		//额外的加密操作。。。
		MemoryStream::Write(data);//写内存流
	}
};

class BufferdFileStream :public FileStream
{
	//...
};

class BufferedNetworkStream :public NetworkStream
{
	//...
};

class BufferedMemoryStream :public MemoryStream
{
	//...
};

class CryptoBufferedFileSream :public FileStream
{
public:
	virtual char Read(int number)
	{
		//额外的加密操作
		//额外的缓冲操作
		FileStream::Read(number);  //读文件流
	}

	virtual void Seek(int position)
	{
		//额外的加密操作
		//额外的缓冲操作
		FileStream::Seek(position); //定位文件流
	}

	virtual void Write(char data)
	{
		//额外的加密操作
		//额外的缓冲操作
		FileStream::Write(data);//写文件流
	}
};

void Process()
{
	//编译时装配
	CrytoFileStream* fs1 = new CrytoFileStream();

	BufferdFileStream* fs2 = new BufferdFileStream();

	CryptoBufferedFileSream* fs3 = new CryptoBufferedFileSream();
}

  类之间的继承关系如下图所示:

 

 采用Decorator模式修改完成之后的代码如下:

//业务操作
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)
	{
		//写文件流
	}
};

class NetworkStream : public Stream
{
public:
	virtual char Read(int number)
	{
		//读网络流
	}

	virtual void Seek(int position)
	{
		//定位网络流
	}

	virtual void Write(char data)
	{
		//写网络流
	}
};

class MemoryStream :public Stream
{
public:
	virtual char Read(int number)
	{
		//读内存流
	}

	virtual void Seek(int position)
	{
		//定位内存流
	}

	virtual void Write(char data)
	{
		//写内存流
	}
};

class DecoratorStream :public Stream
{
protected:
	Stream* stream;              //...

	DecoratorStream(Stream* s) :stream(s)
	{};
};

//扩展操作
class CrytoStream :public DecoratorStream     //这个地方继承Stream只是为了遵循接口规范。
{

public:

	//构造器
	CrytoStream(Stream* s) :DecoratorStream(s)
	{

	}

	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 BufferdStream :public DecoratorStream
{
public:
	BufferdStream(Stream* s) :DecoratorStream(s)
	{

	}

	virtual char Read(int number)
	{
		//额外的缓冲操作。。。

		stream->Read(number);
	}

	virtual void Seek(int position)
	{
		//额外的缓冲操作。。。

		stream->Seek(position);
	}

	virtual void Write(char data)
	{
		//额外的缓冲操作。。。

		stream->Write(data);
	}
};

void Process()
{
	//运行时装配
	FileStream* s1 = new FileStream();

	CrytoStream* s2 = new CrytoStream(s1);

	BufferdStream* s3 = new BufferdStream(s1);

	BufferdStream* s4 = new BufferdStream(s2);   //既加密又缓存
}

  各类之间的继承关系图

 

 

4. 模式定义

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

 

5. 结构

 

 

 

6. 要点总结

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

 

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

 

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