要想正确理解设计模式,首先必须明确它是为了解决什么问题而提出来的。
设计模式学习笔记
——Shulin
转载请注明出处:http://blog.csdn.net/zhshulin
门面模式是对象的结构模式,外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
为子系统提供一个高层次的接口,使子系统易于使用。
适用性:
1)当你要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Facade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过facade层。(简单点说门面就是提供一些基础服务满足大多数用户,而有特殊需求的可以越过门面,直接和系统进行交互)
2)客户程序与抽象类的实现部分之间存在着很大的依赖性。引入facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
3)当你需要构建一个层次结构的子系统时,使用facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们之间的依赖关系。
门面模式是对象的结构模式。门面模式没有一个一般化的类图描述,下图演示了一个门面模式的示意性对象图:
门面(Facade)角色:客户端可以调用这个角色的方法。此角色知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户 端发来的请求委派到相应的子系统去。
子系统(subsystem)角色:可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接 调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
现代的软件系统都是比较复杂的,设计师处理复杂系统的一个常见方法便是将其“分而治之”,把一个系统划分为几个较小的子系统。
医院的例子:如果把医院作为一个子系统,按照部门职能,这个系统可以划分为挂号、门诊、划价、化验、收费、取药等。看病的病人要与这些部门打交道,就如同一个子系统的客户端与一个子系统的各个类打交道一样,不是一件容易的事情。
首先病人必须先挂号,然后门诊。如果医生要求化验,病人必须首先划价,然后缴费,才可以到化验部门做化验。化验后再回到门诊室。
各个具体业务类:
/**
* 挂号
* @author ZSL
*/
public class Register {
public void register(){
System.out.println("进行挂号!");
}
}
/**
* 门诊
* @author ZSL
*/
public class TreatMent {
public void treat(){
System.out.println("治病!");
}
}
/**
* 缴费
* @author ZSL
*/
public class Payment {
public void pay(){
System.out.println("缴费!");
}
}
/**
* 取药
* @author ZSL
*/
public class Drugstore {
public void getDrug(){
System.out.println("取药!");
}
}
/**
* 门面类,相当于医院的接待处
* @author ZSL
*/
public class Facade {
private Register register;
private TreatMent treatMent;
private Payment payment;
private Drugstore drugstore;
public Facade(){
register = new Register();
treatMent = new TreatMent();
payment = new Payment();
drugstore = new Drugstore();
}
//接待处挂号
public void register(){
register.register();
}
//接待处带着病人去治疗,这个地方有点不妥,毕竟病人需要和医生直接打交道,理解就好
public void treat(){
treatMent.treat();
}
//接待处缴费
public void pay(){
payment.pay();
}
//接待处取药
public void getDrug(){
drugstore.getDrug();
}
}
/**
* 客户端
* @author ZSL
*/
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.register();
facade.treat();
facade.pay();
facade.getDrug();
}
}
这个例子在现实中有一个不足之处就是门诊应该让客户端直接和门诊类打交道,其他的都可以通过接待中心(Facade)来进行,方便病人就诊。但是不影响理解门面模式的设计思想,反而更易于理解其思想。门面模式就是取出子系统中各类的基本功能来满足大部分用户的需求,如果有特殊需求,可以和具体类直接交互。
Ø 松散耦合
时客户端与子系统解耦,让子系统内部的模块能更容易扩展和维护。
Ø 简单易用
客户端只需要跟门面类交互就可以了。
Ø 更好划分访问层次
有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到 门面中,这样既方便客户端使用,也很好地隐藏了内部的细节。
不符合开闭原则。所谓的开闭原则是软件工程里面一个最基本的原则:对扩展开放,对修改关闭。换句话说,你的系统可以提供新的功能模块而不必进行修改。