卓's profile成都,又是成都PhotosBlogListsMore ![]() | Help |
|
|
September 27 Decorator场景:
一个应用中,需要将一些文档进行打包传递,这些文档对象被定义为类A。
出于安全的原因,对某些需要保密的文档需要加密,有一个新子类EncryptA来完成这个功能。
由于某些文档很大,传递时为节省空间需要进行压缩,子类ZipA可以完成这个功能。
某些文档在被阅读后,需要发送阅读回执给发送者,子类ReceiptA可以完成。
现在有一些新的需求,我需要一个既可以加密,又可以压缩的对象,怎么实现?
多重继承?这不是一个好办法,在这种情况下,继承关系之间形成了一个菱形关系。
重新写一个新类ZipEncryptA?这是一个办法,可以解决这个问题。但是问题在于已经实现过的功能Encrypt和Zip可能需要在这个新的子类中再写一次;另外,一旦我还需要一个ZipEncryptReceipt功能的文档,上述的工作需要再实现一次。而且一旦这种可以组合的功能比较多,则子类的个数将会呈爆炸性的增长。
这种情况下,考虑使用Decorator是一个不错的处理办法。
结构:
以前面所讲到的文档为例,有一个Document类作为我们需要操作的文档的基类。一个ConcreteDoc,这个类继承自Document,作为一种具体的文档,例如PdfDocument。我们还需要一个DecoratorDoc,这个类同样继承自Document,它是所有的Decorator的基类。DecoratorDoc有一个成员mDoc,这个成员指向一个Document对象。好了,在不使用Decorator模式的情况下,我们通常会这样使用:
Document *pDoc = new PdfDocument();
trans->transfer(pDoc);
在Decorator模式下,如果需要对这个doc实现压缩功能,则实现一个ZipDecoratorDoc,它继承自DecoratorDoc,所有对Document的操作都将转发给mDoc来实现,并且其构造函数的参数中必须含有一个指向Document对象的指针。如果需要一些特别的操作,则可以进行附加。例如,对于getContent之类的操作,可以附加解压缩行为。setContent操作上可以附加压缩行为。那么,这种模式下上述的代码则变为:
pDoc = new PdfDocument();
trans->transfer(new ZipDecoratorDoc( pDoc ) );
对于Document的使用者来说,它只知道操作的是一个Document。
对于这种情况来说,还没有体现出Decorator的好处。因为我们可以通过继承的方式完成同样的功能。如果我们还需要同时对它进行加密,则我们依然从DecoratorDoc中派生出一个新类EncryptDecoratorDoc实现加密功能。则上述代码演化为:
pDoc = new PdfDocument();
trans->transfer(new EncryptDecoratorDoc( new ZipDecoratorDoc( pDoc ) ) );
通过级联的方式,同时实现了加密和压缩的功能。
这样,我们可以通过类的组合来实现功能的组合。
这种方式比单纯的静态继承更灵活,添加实现某一功能的类要比添加多种功能的类更容易实现。通过类的组合的使用的方式,也减少了子类的个数。 September 21 BRIDGE桥接什么时候使用桥接? 1. 当不希望一个抽象和它的接口之间存在一个固定的绑定关系时。例如,程序运行时刻希望实现可以被替换,比如,你需要一个collection,当数据不需要频繁增删时,用数组最方便,当数据频繁添加删除时,则链表比较合适,可以通过运行时刻的情况来决定使用哪种implementor。 2. 希望类的抽象和其实现部分都可以有自己的继承层次。典型情况是,你正在为某一个标准编写一个实现(例如,为DOM标准编写实现),这个标准有自己的类层次,而你为其编写的实现类可能需要一个不完全相同的层次。在JAVA中由于有interface的存在这个问题很容易解决,对于C++来说则比较困难,多重继承可以解决部分问题,但是会带来一些麻烦。这时使用桥接模式将是一个好的解决办法。 3. 对客户隐藏实现(C++),因为Implementor不需要提供头文件 4. 对抽象进行修改时,实现部分代码不需要重新编译。(这算是一个附带的好处,对于代码特别庞大的工程,桥接模式将大量节省编译时间) 5. 什么时候该使用桥接?对于C++代码,简单来说可以这样判断:如果你有一个抽象类,这个抽象类存在一个或多个派生类,并且这些派生类也是抽象类时,你需要考虑是不是用桥接模式来实现。 September 20 原型(PROTOTYPE)的应用范围?原型的应用场景:
1。Client使用一个(或多个)Product
2。Client作为框架,是通用的。Product作为被Client使用的产品,是一个抽象的类(接口)。在使用这个框架时,可能会新增加一些concrete product。
3。Client在设计时,作为框架,它是不可能知道concrete Product是什么product,所以也无法去实例化一个具体的product。
4。然而在应用中,某些时候Client也确实需要创建一个新的concrete。
矛盾在于:
Client需要创建新的对象(concrete product),但是又不知道新的concrete product如何创建,因为concrete product是框架(Client)完成之后新写的,Client无法调用其构造函数。
解决办法:
为product类声明一个clone方法,这个方法可以复制一个和当前对象一样的新对象,来达到创建新对象的目的。
运行时刻,将新增加的类创建一个原型对象,并将这个对象交给client,这样,client在不知道product的类型的情况下却可以使用原型来创建新对象,达到动态加载的目的。
实现原型模式的一些关键点:
1。克隆操作:考虑深浅拷贝、循环引用等问题
2。初始化:如何合理、方便的初始化新对象
3。原型管理:有多个原型时,如何对其管理(可使用注册、关联等办法) February 09 Abstract factory
February 06 VISITOR - 访问者有些细节还在领悟中,To be continued。
附加一个说明,有疑问之处我将用红色标注,我自己附加的理解使用下划线标注。
January 27 SINGLETON - 单件SINGLETON应该是设计模式中最简单易懂的一种,也是我在第一遍阅读中唯一记住的一种模式。
January 26 开天辟地第一篇 读书前的动员和思想工作《设计模式》这本书,估计是在02年的夏天买的,到今天算算也有四个年头了。其中,在科银18楼我的桌面上躺了一年,借给老钱看了差不多一年,然后又继续在科银16楼躺了一年多,到了今天,我终于准备开始看了。
其实一直很清楚模式对于设计的重要性:前辈们无数实践的经验总是比我一个毛头小子的知识来得丰富些吧?不过清楚归清楚,行动却总是没和思想觉悟保持一致。一方面因为该书比较抽象,读起来晦涩不容易理解;另一方面,也是主要原因,是因为我的懒惰。所以,过去的四年中,尽管开了无数次头,读书的计划却始终没有完成。 今天终于下定决心,趁春节放假空暇把此书读完。促使我下定决心的原因是最近的项目中,使用到的方案其实就是设计模式中一个很典型的模式,由于我的无知,始终不能在代码中完美的实现,而是不断的花费时间去修正代码,其结果反而让结构更乱了。 嗯,动员工作完成,每理解透一个模式,再上来做思想汇报。 |
|
|