设计模式之装饰器模式
程序员文章站
2022-05-27 23:43:53
...
最近看到《设计之禅》的装饰器模式,特用C++实现了一遍,发现有些有意思的东西需要探究一下。
UML类图:
一. 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()。
下一篇: 复习篇-mysql