模式开发之旅(16):外观模式
2010-08-11 11:18:07外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式是一种很简单的设计模式,但是它却非常常用。对于面向对象有一定基础的朋友,即使没有听说过外观模式,也完全有可能在很多时候使用它,因为它完美地体现了依赖倒置原则和迪米特法则的思想。对于一个复杂的系统它的底层逻辑可能相互之间充满依赖,前端程序调用起来可能会出现逻辑不清晰,类和类之间相互耦合。比如我们给学校图书馆开发一套系统,系统可以为用户提供续借图书、预借图书、提交罚款等功能,然后每一个功能的实现逻辑可能会很复杂。我们那预借图书这个功能来举例:用户在线对某本书籍发出预借请求,系统收到请求后。首先需要判断该用户是否拥有预借权限,然后此本书是否可以被预计,是否达到最大预计次数,如果全部通过则预借成功。对于最底层的逻辑来说,判断预借权限、是否在允许的预借次数下以及处理预借请求可能在不同的类的不同方法中实现,想想如果对于客户程序,它处理预借请求需要调用多个方法,这样前台代码和后台逻辑就紧密的耦合在一起,如果底层逻辑发生变化,前台代码可能也要跟着发生变化,这样的设计将是很脆弱的。但是如果我们在前台代码与后台逻辑中间引入一个外观类,这个外观类帮助我们调用底层的逻辑步骤,而对于前台代码来说它只需要调用外观类中对应的一个续借方法得到返回值就可以了,这样前后台的代码就没有耦合在一起了,底层逻辑的变化也不会影响到前台客户的代码调用。
此模式使用起来比较简单,只需要多添加一个类就可以了。这里我就不再列出详细代码了。
那在什么时候使用外观模式呢?我们将系统设计分3个阶段来说明。首先在设计初级阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层与表示层的层与层之间建立外观,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。其次,在开发阶段,子系统往往因为不断的重构而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但外部调用它们的用户程序却带来了困难,增加一个外观可以提供一个简单的接口,减少它们之间的依赖。第三,在维护一个遗留的大型系统时,这个系统可能已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它,此时使用外观模式也是非常合适的。
结构图
几个要点
从客户程序的角度来看, Facade模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到Façade接口的变化。
Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。Facade很多时候更是一种架构设计模式。
我们知道,类、模块、系统之间的“通信”,一般都是通过接口调用来完成的。接口设计的好坏,直接影响到类、模块、系统是否好用。所以,我们要多花点心思在接口设计上。完成接口设计,就相当于完成了一半的开发任务。只要接口设计得好,那代码就差不到哪里去。接口粒度设计得太大,太小都不好。太大会导致接口不可复用,太小会导致接口不易用。在实际的开发中,接口的可复用性和易用性需要“微妙”的权衡。针对这个问题,一个基本的处理原则是,尽量保持接口的可复用性,但针对特殊情况,允许提供冗余的门面接口,来提供更易用的接口。