重新设计会影响软件系统的许多方面,并且未
曾料到的变化总是代价巨大的。
设计模式可以确保系统能以特定方式变化,从而帮助你避免重新设计系统。每一个设计
模式允许系统结构的某个方面的变化独立于其他方面,这样产生的系统对于某一种特殊变化
将更健壮。
下面阐述了一些导致重新设计的一般原因,以及解决这些问题的设计模式:
1) 通过显式地指定一个类来创建对象在创建对象时指定类名将使你受特定实现的约束
而不是特定接口的约束。这会使未来的变化更复杂。要避免这种情况,应该间接地创建对象。
设计模式: Abstract Factory,Factory Method,P r o t o t y p e 。
2) 对特殊操作的依赖当你为请求指定一个特殊的操作时,完成该请求的方式就固定下
来了。为避免把请求代码写死,你将可以在编译时刻或运行时刻很方便地改变响应请求的方
法。
设计模式: Chain of Resposibility,C o m m a n d
3) 对硬件和软件平台的依赖外部的操作系统接口和应用编程接口( A P I )在不同的软硬件
平台上是不同的。依赖于特定平台的软件将很难移植到其他平台上,甚至都很难跟上本地平
台的更新。所以设计系统时限制其平台相关性就很重要了。
设计模式: Abstract Factory(3.1),B r i d g e ( 4 . 2 )。
4) 对对象表示或实现的依赖知道对象怎样表示、保存、定位或实现的客户在对象发生
变化时可能也需要变化。对客户隐藏这些信息能阻止连锁变化。
设计模式: Abstract Factory(3.1),B r i d g e ( 4 . 2 ),M e m e n t o ( 5 . 6 ),P r o x y ( 4 . 7 )
5) 算法依赖算法在开发和复用时常常被扩展、优化和替代。依赖于某个特定算法的对
象在算法发生变化时不得不变化。因此有可能发生变化的算法应该被孤立起来。
设计模式: B u i l d e r ( 3 . 2 ),I t e r a t o r ( 5 . 4 ),S t r a t e g y ( 5 . 9 ),Template Method(5.10) ,
Vi s i t o r ( 5 . 11 )
6) 紧耦合紧耦合的类很难独立地被复用,因为它们是互相依赖的。紧耦合产生单块的
系统,要改变或删掉一个类,你必须理解和改变其他许多类。这样的系统是一个很难学习、
移植和维护的密集体。
松散耦合提高了一个类本身被复用的可能性,并且系统更易于学习、移植、修改和扩展。
设计模式使用抽象耦合和分层技术来提高系统的松散耦合性。
设计模式: Abstract Factory(3.1) ,C o m m a n d ( 5 . 2 ),F a c a d e ( 4 . 5 ),M e d i a t o r ( 5 . 5 ),
Observer(5.7) ,Chain of Responsibility(5.1)。
7) 通过生成子类来扩充功能通常很难通过定义子类来定制对象。每一个新类都有固定
的实现开销(初始化、终止处理等)。定义子类还需要对父类有深入的了解。如,重定义一个操
作可能需要重定义其他操作。一个被重定义的操作可能需要调用继承下来的操作。并且子类
方法会导致类爆炸,因为即使对于一个简单的扩充,你也不得不引入许多新的子类。
一般的对象组合技术和具体的委托技术,是继承之外组合对象行为的另一种灵活方法。
新的功能可以通过以新的方式组合已有对象,而不是通过定义已存在类的子类的方式加到应
用中去。另一方面,过多使用对象组合会使设计难于理解。许多设计模式产生的设计中,你
可以定义一个子类,且将它的实例和已存在实例进行组合来引入定制的功能。
设计模式:B r i d g e ( 4 . 2 ),Chain of Responsibility(5.1),C o m p o s i t e ( 4 . 3 ),D e c o r a t o r ( 4 . 4 ),
O b s e r v e r ( 5 . 7 ),S t r a t e g y ( 5 . 9 )。
8) 不能方便地对类进行修改有时你不得不改变一个难以修改的类。也许你需要源代码
而又没有(对于商业类库就有这种情况),或者可能对类的任何改变会要求修改许多已存在的其
他子类。设计模式提供在这些情况下对类进行修改的方法。
设计模式: A d a p t e r ( 4 . 1 ),D e c o r a t o r ( 4 . 4 ),Vi s i t o r ( 5 . 11 )。