`
pleasetojava
  • 浏览: 705302 次
  • 性别: Icon_minigender_2
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

设计模式面面观(13):外观模式(Facade Pattern)-结构型模式

阅读更多

概述:

在软件开发中我们常常遇到这样的问题,在一个系统中有多个子系统,而一个应用型的类(客户类)需要和各个子系统打交道来完成一件事情,这样客户代码就会和子系统类耦合。在生活中我们也会遇到这样的问题,打个比方:买房子。我在买房子的时候首先是选,到一个房产开发商那里有售楼小姐给你做介绍,你选中好房子后要办理贷款,签合同,办贷款的时候还要咨询贷款额度,让公司开收入证明,还款类型,指定贷款年。然后还要到售楼处去办理定金,一星期内还要交首付。在这个过程中我要和售楼小姐、我所在的公司、银行,售楼出出纳员,售楼经理好多人打交道,大家试想下如果这个就是一个系统的业务流程那么作为我(用户)需要和这个系统中的子系统多次打交道,这样就形成了客户程序与复杂的系统内部子系统间的紧耦合,从而导致客户程序随着子系统变化而变化。那如何简化客户程序和子系统间的交互呢,这里我们需要再添加一个买房统一接口类(SellMan),帮我做买房的事情这样客户程序(我)不再依赖系统中的子系统。这就是外观模式。看下图:

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 414.75pt; HEIGHT: 296.25pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5CFANWEI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.emz" o:title=""></imagedata></shape>

解释:

1. 定义一个IBack接口创建PutOUt 放款方法

2. 定义一个IAccountCredit接口创建HasGoodCredit 判断是否可以贷款方法

3. 定义一个Back银行的抽象类,继承IBackIAccountCredit接口

4. 定义工商(BusinessBack)、农业(AgroBack)、建设(ConstructBack)、交通(TranfficBack)四大银行继承自Back

5. 定义一个ISell接口创建Sell 卖房方法

6. 创建LandAgent房产商继承ISell接口

7. 创建House房屋类

8. 定义一个IBuyHouse接口创建Buy 买房方法

9. 创建SellMan买房屋代理人

10. 创建Client买房人

这样一来客户程序和子系统的通信有中间的SellMan统一协调,通过SellManBuy接口做买卖,这样就实现了解耦合。来看看他的客户端的代码把,如此简单:

Client client = new Client();

client.Name = "范伟伟";

client.CreditCount = 500000;

SellMan sell = new SellMan(client);

House house=sell.Buy(100000);

if (house != null)

Console.WriteLine(string.Format("{0}{1}房屋卖给了{2}", sell.LandAgent.Name, house.ID, client.Name));

else

Console.WriteLine("交易失败");

效果:

OOD设计合理性:

1. 是否符合开不原则:

客户程序和子系统的通信有中间的SellMan统一协调,通过SellManBuy接口做买卖,再做修改时只要修改SellMan Buy 方法或再创建一个继承了Buy接口的类

符合

2. 是否符合里氏代换:

符合

3. 是否符合抽象原则

符合

4. 是否符合迪米特法则

符合

装饰模式总结

意图:

为子系统中的一组接口提供一个一致的界面,Façade模式定义了一个高层接口,这个接口使得子系统更加容易操作

结构图:

<shape id="_x0000_i1026" style="WIDTH: 191.25pt; HEIGHT: 204.75pt" type="#_x0000_t75" alt=""><imagedata src="file:///C:%5CDOCUME~1%5CFANWEI~1%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.gif" o:href="资料/设计模式(15)-Facade%20Pattern%20-%20First%20we%20try,%20then%20we%20trust%20-%20博客园_files/Pic90.gif"></imagedata></shape>

门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。

子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。

使用背静:

1. 为一个复杂系统提供一个简单的统一的接口

2. 客户程序与抽象类的实现部分之间存在着很大的依赖性

3. 当需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。

模式优缺点:

优点:

1. 他对客户屏蔽了系统组件,因此减少了客户处理的对象的数目并使得子系统使用起来更加方便

2. 使得子系统与客户程序间的松耦合

3. 他并不限制他们使用子系统类,你可以在系统易用性和通用性之间加以斟酌

注意:

1. 降低客户-子系统之间的耦合度。

用抽象类实现Façade而他的具体子类对应于不同的子系统实现,这可以进一步降低客户与子系统的耦合度。(这里SellMan我没有用抽象类是因为我只为买卖这一层做Facade)。这样,客户就可以通过抽象的Façade类接口与子系统通讯。这种抽象耦合关系使得客户不知道它使用的是子系统的哪一个实现

除了生成子类的方法外,另一种方法是用不同的子系统对象配置Façade对象。为定制façade,近需对他的子系统(一个或多个)进行替换即可。

2. 公共子系统类与私有子系统类

C#不支持私有接口的实现所以这里不多讲

源代码 下载
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics