老生常谈:外观模式

    名词解释:外观:

       ①事物的外在形象:他外观宽绰,其实已经负债累累|这栋旧宅外观尚可,而内部已被白蚁蛀空。  

       ②外貌:外观整洁|既要注重外观,更要注重内在的修养。

    外观模式:外观模式(Facade pattern)涉及到子系统的一些类。所谓子系统,是为提供一系列相关的特征(功能)而紧密关联的一组类。外观模式其实说的通俗一点就是起到化零为整的作用。

 

    下图为没有应用外观模式时的类图:可以看出客户端代码直接与子系统类的耦合度太强。

 

    

    下面是应用了外观模式的类图:可以看出客户端只与外观类耦合,成功的与杂乱而多的子系统解耦。组装的任务就交给外观类去完成了。

 

 

     例如:一部F1赛车,它在比赛结束后都会被肢解为大大小小的零件,在下次开始比赛时又会把这些零件一一组装起来变成一部看起来十分亮眼的赛车。如果你面对一堆的零件,你要想把它开动,要如何是好呢?当然你会想到先把它组装起来。你之所以第一时间想到把它先组装起来,是因为你知道只要它变成一辆赛车(而不是一堆零件),然后一按启动按钮,赛车就会启动。原本是一堆看起来零乱的东西,为什么经过组装后操作就会变得如此简单呢,只要按一下,车就会全身动起来,而不是一个地方动呢?这里汽车设计师们就应用了外观模式。原来赛车的启动程序是非常复杂的,本人引用一个百度知道的内容:

    启动机通电后,磁力线圈,产生吸力,吸住拨叉,通过杠杆原理,把单向齿轮推出去,与发动机后部的飞轮捏合,与此同时,通电后的启动机转子会旋转,而单向齿轮通过花键随转子转动,带动发动机转动,从而启动!

    可见汽车的启动在内部是发生很多事情的,并不是一件事就解决问题了。上面的解释中:磁力线圈,产生吸力,吸住拨叉,通过杠杆原理,把单向齿轮推出去,这些内部的操作过程对于一般司机来说意义并不大,司机也不想去了解它的工作原理,要不然司机不都是汽车工程师了。司机的责任只是驾驶它,并不用去了解它的本质。既然不用了解工作原理,那汽车设计师就必须让司机非常方便的学会开车,例如让司机按一个开关汽车就会启动,实际生活中,他们也就是这样做的。

    上面生活中的例子在程序设计中也是一样的,往往在客户端程序中的一个功能应用会涉及到子系统中很多组件,如果客户端程序调用中出现大量的子系统代码,那么会有以下几个弊端:

    1:客户端代码过大,不容易维护。

    2:客户端代码依赖子系统,子系统一旦有变化,客户端程序就要变,这违背了开闭原则的编程规则。

   下面以一个网上投票的例子来说明一下。投票的流程如下:

      第一:检测是否是登录用户,如果未登录则提示登录。

      第二:登录用户余额是否充足,不足则提示。

      第三:防止用户刷票。

      第四:用户投票,并扣除用户费用。

    1:客户端页面代码:由于本文主旨在外观模式,为此在登录,扣费的地方就简单化了,登录用一个输入框完成,用户的帐户信息都是事先存储好的。只是为了说明问题而已。

Code

 

   cs:  

Code

 

    2:子系统代码:客户端代码并不是特别的多,但总觉的看起来不太清晰,有点把业务逻辑层的功能占用的嫌疑。这里就是一个投票功能,为何要在客户端代码中加入如此多的业务处理呢?(投票规则判断),如果能写成一个方法就好了。

Code

 

    3:改进代码:子系统代码不变 。客户端投票代码:

    4:新增外观类:

Code

 

    5:客户端调用代码如下:可见看起来简化多了。通过新增加的外观类,成功的把复杂的业务判断分散到外观类中,客户端只与外观类有直接关系,从而使得客户端与子系统之间解耦,外观模式在应用的时候,同时 允许客户端直接访问子系统,这样就和没有用外观模式时一样,这种情况大多应用在比较老的系统中,老系统由于升级,应用了外观模式,可是有的地方还须要直接 用到子系统。

Code

 

    上面的外观类中采用了单件模式,可能有朋友会说在这里面可能是为了模式而模式,我想申明的是,本文属于个人观点,具体采用与否关键在于实际开发者。别人说的再多,再好,也比不过自己的实践。理论是实践的指导,而实践则是理论的见证。 

本文引用:

        http://dev.yesky.com/203/2175203.shtml

posted on 2008-08-11 17:26  min.jiang  阅读(2716)  评论(1编辑  收藏  举报