标签:
很多时候你会发现子类在不断增加,有时候甚至难以控制,虽然继承是面向对象的一大特征,但是继承并不是项目中所提倡,合成复用设计原则就告诉我们能够使用合成的地方尽量不要使用继承。对于继承来说还有一个很大的缺点,那就是内存占用与子类的层次是成正比关系的,这个也很好理解,实例化子类的时候总是要先调用最顶层父类的构造方法,然后依次调用低层次的父类直到自身初始化,这个过程实际上是很耗内存的。那么,问题就来了,我们经常会扩展一个类的某个方法,是不是没扩展方法都有必要新增一个子类呢?答案是否定的,在某种情况下我们可以采用装饰模式很好的避免子类的泛滥。
避免过多的子类,动态添加职责
装饰模式用在穿衣服身上在好不过了,如果把穿袜子、穿裙子、穿短裤 看成是一个人打扮方法的不同实现话,那么是不是可以采用继承呢?如果想要动态控制动作的顺序和动作的个数那么,可能有 6+3+3 = 12 个子类;这个时候如果采用装饰模式,把每一个动作都分离作为最原子的操作,然后,对于动作个数和动作顺序通过顺序添加这些原子动作来完成,那么,只需要3个类就能完成。
Java IO流的控制,字节流到字符流的过程 ,就是一个典型的装饰模式,不过IO流的特点似乎没有把装饰模式发挥得淋漓尽致,因为字符流可以装饰字节流,但是字节流貌似装饰不了字节流,也就是在顺序上没有使用到装饰模式,只是在动作的个数上使用了装饰模式。
需要把所需的功能按正确的顺序串联起来进行控制,然而这些动作都是同一类型的时候,可以使用装饰模式;
装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
Component是一个动作的抽象接口,ConcreteComponent 其实是一个最上层的装饰角色,换句话说所有的装饰都是基于他的,比如人穿衣服这个装饰过程,ConcreteComponent 应该是初始化接收具体哪个人,而后面装饰时则对人穿衣服的动作进行装饰。也就是ConcreteDecorator可以接收ConcreteComponent 和 ConcreteDecorator 进行装饰。很好的例子就是Java IO流中有个FileInputStream,不管后面如何缓冲或者字符流装饰,都必须先用FileInputStream初始化一个File对象。
装饰模式中ConcreteComponent有些时候并不是总是必须的,有些时候可以省去ConcreteComponent ,而直接只有装饰对象,这样其实也很好理解。
每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到装饰链中。
装饰模式是为已有的功能添加更多的功能的一种方式。当系统需要新功能的时候,是向旧的类中添加新的代码。这些新家的代码通常了装饰了原有类的核心职责或主要行为。
装饰模式的原理是:他把每个要装饰的功能放在单独的类中,并让这个类包装他所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。
这个模式最主要的优点就是减少子类的泛滥。
这个设计模式和下一个设计模式:代理模式 很相似,具体哪些相似,就在代理模式那里总结了。
标签:
原文地址:http://my.oschina.net/heweipo/blog/425145