设计模式之装饰器模式

最近看到《设计之禅》的装饰器模式,特用C++实现了一遍,发现有些有意思的东西需要探究一下。
UML类图:

 decorator

 

一. C++实现

#include <stdio.h>


/// Base
class Component
{
public:
	virtual ~Component(){}
	virtual int operate() = 0;
};


/// ConcreteComponent
class ConcreteComponent: public Component
{
public:
	ConcreteComponent()
	{
		
	}
	
	virtual ~ConcreteComponent()
	{
		printf("ConcreteComponent Destroy %#04x\n", this);
	}
	
	int operate()
	{
		printf("ConcreteComponent operate\n");
		return 0;
	}
};


/// Decorator
class Decorator: public Component
{
public:
	virtual ~Decorator()
	{
		printf("Decorator destroy:%#04x base:%#04x\n", this, m_component);
		
		delete m_component;
		m_component = NULL;
	}
	
protected:
	Component* m_component;
};


/// ConcreteDecoratorA
class ConcreteDecoratorA: public Decorator
{
public:
	explicit ConcreteDecoratorA(Component *ins)
	{
		m_component = ins;
	}

	~ConcreteDecoratorA()
	{
		printf("ConcreteDecoratorA destroy:%#04x\n", this);
	}
	
	int operate()
	{
		int ret = m_component->operate();
		
		printf("ConcreteDecoratorA operate\n");
		return ret;
	}
};


/// ConcreteDecoratorB
class ConcreteDecoratorB: public Decorator
{
public:
	explicit ConcreteDecoratorB(Component *ins)
	{
		m_component = ins;
	}
	
	~ConcreteDecoratorB()
	{
		printf("ConcreteDecoratorB destroy:%#04x\n", this);
	}
	
	int operate() 
	{
		int ret = m_component->operate();
		
		printf("ConcreteDecoratorB operate\n");
		return ret;
	}
};


// 检测指针是否释放
Component *p = NULL, *q = NULL, *h = NULL;

/**
 * main
 */
int main(int argc, char **argv)
{
	Component *component = new ConcreteComponent(); 	p = component;
	component = new ConcreteDecoratorA(component);		q = component;
	component = new ConcreteDecoratorB(component);		h = component;
	component->operate();
	
	printf("Concrete:%#04x Concrete1:%#04x Concrete2:%#04x\n\n", p, q, h);
	
	// 内存是否泄露?
	delete component;
	component = NULL;
	
	return 0;
}

 

装饰器模式提供比继承更有弹性的扩展方案,缺点产生了大量包装类,业务逻辑比较复杂。

上图实现是调用了三次new,却只delete一次,是否会发生内存泄露?

 

先看结果:

ConcreteComponent operate
ConcreteDecoratorA operate
ConcreteDecoratorB operate
Concrete:0x21d9010 Concrete1:0x21d9030 Concrete2:0x21d9050

ConcreteDecoratorB destroy:0x21d9050
Decorator destroy:0x21d9050 base:0x21d9030
ConcreteDecoratorA destroy:0x21d9030
Decorator destroy:0x21d9030 base:0x21d9010
ConcreteComponent Destroy 0x21d9010

 

分析:在析构ConcreteDecoratorB后,会再析构父类Decorator,但此次的Decorator已被构造函数替换成ConcreteDecoratorA,则析构ConcreteDecoratorA,同理再析构ConcreteComponent。通过Componenet成员变量达到析构了所有堆变量,实在是高!

 

 二. java IO

Java IO提供很多实用的工具类,各种read(), readLine() 调用,典型的装饰器模式。

FileInputStream fis = new FileInputStream("~/test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(b, off, len);

 

源码跟踪:

BufferedInputStream::read(b, off, len);

getInIfOpen().read(b, off, len);

InputStream::read(b, off, len);

 

 

BufferedInputStream利用缓冲输入改善行为,底层调用FileInputStream的read(),而FileInputStream调用InputStream的read()。

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值