设计模式在架构设计中的运用

1 引言
架构是一个软件的骨架。为了应对需求变更,架构设计需要有足够的弹性去适应变化;架构的任何修改都将导致大量代码的重写,从而导致成本上升、工期延长。而设计模式本来主要是针对编码阶段的,但在进行架构设计时,软件架构师可以将组件之间的关键接口通过“灰包图”的形式———指定接口类所使用的设计模式———给程序员更多的指导;并且让架构更具弹性,更能适应各种变化。

2 架构设计与设计模式的关系
“设计模式”是Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides在《设计模式:可复用面向对象软件的基础》中提出来的。在此书中一共介绍了23种面向对象的设计模式;根据模式的应用目的,又将它们分为3类:创建型、结构型和行为型。而设计模式的作用则可以概括为四个字:“封装变化”。“架构”有很多种定义,《软件架构设计》一书对架构的各种定义做了详细的分析和总结;概括出架构不外乎包含“组件”、“交互”和“决策”三个方面。其中决策的最主要目的是要保证架构能适应需求变更。因此,架构设计就是:确定系统有哪些组件,它们之间有什么交互,以及未来可能发生什么变化;然后决定如何去应对变化。也就是说,在架构设计中最重要的事情就是要“隔离变化”。
所以,设计模式是架构设计与编码实现之间的一个桥梁。

3 变化的起源
要在架构设计中正确运用设计模式,首先要明白有哪些变化形式;然后再考虑选择什么设计模式去应对此变化。在《设计模式》一书中列举了以下导致需要重新设计的因素:通过显式地指定一个类来创建对象;对特殊操作的依赖;对硬件和软件平台的依赖;对对象表示或实现的依赖;算法依赖;紧耦合;通过生成子类来扩充功能;不能方便地对类进行修改。单纯地列举这些因素是不够的,还要对变化形式进行分类,以后才能正确地应对变化。其实程序的功能,就是子系统对外交互的“接口”;概念,就是“抽象类”,这也是“接口”;编码实现,则是具体的“代码”。为了尽量重用已有代码,或者预见到代码将来会发生变化。这些变化,最终都可以看成是代码库的替换。所以,架构设计要考虑的变化就是
“交互接口”和“编码实现”的变化。

4 设计模式在架构设计中的运用
要让设计的架构能适应变化,就是要预见组件之间的交互接口和编码实现将来可能发生什么变化,并对此做出正确的决策:采用正确的设计模式去封装变化。可以将交互接口或编码实现前后的变化分为4大类。下面将分别给出有效的决策方案,即:指明了关键类设计模式的“灰包图”。

4.1 相似接口,相同功能
在做架构设计时,根据需要设计出的接口可能与现有代码不相同;或者想暂时使用第三方的SDK实现,将来可能会改为自己实现。为了重用代码、隔离变化,可以运用ADAPTER模式去匹配接口;将变化封装在一个独立的Component内。将来就算第三方的SDK发生了变化或替换为自己的新代码,我们都只需重写Adapter类,影响范围也仅限于Component。这种情景类似于通过USB转换头去匹配不同大小的USB接口。

4.2 不同接口,相似功能
在做架构设计时,很多软件都要求支持跨平台。虽然有可能各个开发平台的已经有相似的功能,但他们的工作方式和开发接口却有可能完全不同;不能使用上述ADAPTER模式去解决。在这种情况下,可以按软件本身的需求抽象出相关的功能接口(如IWindow、I3DWindow和IFaceWindow);然后再使用BRIDGE模式充分重用平台已有的功能,同时又做到了隔离变化,将平台相关的代码限制在单独的一个Platform包中。

4.3 增替“实现”
有时做架构设计时,会预见到将来也许需要调整或增加某些功能。比如原来保存功能默认是保存成纯文本格式,将来可能要让它支持保存成RTF、HTML等;或者字符串原来是用IDEA加密,将来要换成DES加密;等等。这种情景下,关键是要分离接口与实现;可以运用STRATEGY模式解决。

4.4 精简接口
在做架构设计时,有时也能预见到系统中对象的数目会不断增加。那么两两之间的交互数就会急剧上升,彼此间的依赖关系也将变得非常复杂。为了限制或控制对象之间的交互,可以利用FACADE模式将相关的对象封装成包、模块或子系统,加大组件的粒度、降低耦合;从而增加架构的灵活性,适应变化。

5 总结
“完美之道,不在无可增加,而在无可删减。”在做架构设计时,只要先将最核心和最必要的功能设计出来,然后再考虑如何提供增加功能和预防变化的机制,就能保证设计的稳定。设计模式是最常用的封装变化的方法,我们要善于运用。

你可能感兴趣的:(设计模式)