`

Façade Pattern

阅读更多

目前整理的门面模式 的使用有三种情况。下面分别讨论。

 

    第一种情况

 

客户类要使用的功能分布在多个类中,这些类可能相互之间没有什么关系;客户在使用后台的时候,必须先初始化要使用到的功能所在的类,然后才能使用。这时候,适合将这些功能集中在一个Façade类里,还可以替用户做一些初始化的工作,以减轻用户的负担。

 

例如,以商店为例。假如商店里出售三种商品:衣服、电脑和手机。这三种商品都是由各自的生产厂商卖出的,如下:
public class CoatFactory
{
        public Coat saleCoat()
        {
               ……
               return coat;
}
……
}
然后是电脑的厂家类:
public class ComputerFactory
{
        public Computer saleComputer()
        {
               ……
               return computer;
}
……
}
最后是手机商类:
public class MobileFactory
{
        public Mobile saleMobile()
        {
               ……
               return mobile;
}
……
}
如果没有商店,我们就不得不分别跟各自的生产商打交道,如下:
//买衣服
CoatFactory coatFactory = new CoatFactory();
coatFactory.saleCoat();
//买电脑
ComputerFactory computerFactory = new ComputerFactory();
computerFactory.saleComputer();
//买手机
MobileFactory mobileFactory = new MobileFactory();
mobileFactory.saleMobile();
对我们顾客来说,和这么多的厂家类打交道,这显然是够麻烦的。
这样,我们就需要创建一个商店类了,让商店类和这些厂家打交道,我们只和商店类打交道即可,如下:
public class Store
{
        public Coat saleCoat()
        {
               CoatFactory coatFactory = new CoatFactory();
return coatFactory.saleCoat();
}
public Computer saleComputer()
{
               ComputerFactory computerFactory = new ComputerFactory();
return computerFactory.saleComputer();
}
public Mobile saleMobile()
{
       MobileFactory mobileFactory = new MobileFactory();
return mobileFactory.saleMobile();
}
}
好了,现在我们要买东西,不用去跟那么多的厂家类打交道了。
Store store =new Store();
//买衣服
store.saleCoat();
//买电脑
store.saleComputer();
//买手机
store.saleMobile();
呵呵,这样对我们客户类来说,是不是简单多了。
第二种情况

 

客户要完成的某个功能,可能需要调用后台的多个类才能实现,这时候特别要使用Façade模式。不然,会给客户的调用带来很大的麻烦。请看下面的例子。
我经常看到后台编码人员,强迫它们的使用者写出如下的代码:
                ……
String xmlString = null;
          int result = 0;
          try
          {
                   xmlString = gdSizeChart.buildDataXML(incBean);
             
             
              String path = "D:/Eclipse3.0/workspace/PLMSuite/AppWeb/PM/productSpecification/gridfile.xml";
              File f = new File(path);
              PrintWriter out = new PrintWriter(new FileWriter(f));
              out.print(xmlString);
              out.close();
            System.out.println("\r\n\r\n sumaryAction" + xmlString + "\r\n\r\n");
              request.setAttribute("xmlString", xmlString);
          }
          catch(Exception ex)
          {
              ex.printStackTrace();
          }
这段代码前面即省略号省略掉的一部分是客户类调用后台的一部分代码,是一个相对独立的功能。后面这一部分也是一个相对独立的功能,而后台代码设计人员却把这个功能留给客户类自己来实现。
我就很怀疑,让客户类做这么多事情,到底要你的后台做什么?你还不如直接把所有的事情都给客户类做了得了。因为,你后台做了一半,剩下的一部分给客户类做,客户类根本就不明白怎么回事,或者说他不清楚你的思路,这样做下去更加困难。可能这点逻辑对你来说,很简单。但使用者不明白你的思路啊,他不知道来龙去脉,怎么往下写?
如果在这里有一个Façade类,让它来做不该由客户类来做的事,是不是简单多了呢?如下是一个Façade类:
public class Façade
{
        public static void doAll(PE_MeasTableExdBean incBean, HttpServletRequest request)
        {
               ……
               request.setAttribute(“xmlString”,Façade.getFromOut(incBean));
}
        private static String getFromOut(PE_MeasTableExdBean incBean)
        {
               try
          {
                   xmlString = gdSizeChart.buildDataXML(incBean);
             
             
              String path = "D:/Eclipse3.0/workspace/PLMSuite/AppWeb/PM/productSpecification/gridfile.xml";
              File f = new File(path);
              PrintWriter out = new PrintWriter(new FileWriter(f));
              out.print(xmlString);
              out.close();
            System.out.println("\r\n\r\n sumaryAction" + xmlString + "\r\n\r\n");
              return xmlString;
          }
          catch(Exception ex)
          {
              ex.printStackTrace();
                       return null;
          }
}
}
那么客户类的调用就是下面的样子:
Façade.doAll(incBean,request);
这样,客户是不是轻松多了?值得注意的是,Façade类中的getFromOut方法其实不应该在Façade类中,本文为了简单起见而放在了这个类中,对Façade类来说是不符合单一职责原则的。
最后总结一下第二种情况的模式。后台为实现某一个功能有如下类:
public class ClassA
{
        public void doA()
        {
               ……
}
……
}
public class ClassB
{
        public void doB()
        {
               ……
}
……
}
public class ClassC
{
        public void doC()
        {
               ……
}
……
}
如果客户类需要这样调用:
……
ClassA a = new ClassA();
a.doA();
ClassB b = new ClassB();
b.doB();
ClassC c = new ClassC();
c.doC();
……
那么就适合做一个Façade类,来替客户类来完成上述的功能,如下:
public class Façade
{
        public void doAll()
        {
               ClassA a = new ClassA();
a.doA();
ClassB b = new ClassB();
b.doB();
ClassC c = new ClassC();
c.doC();
}
}
则客户类的调用如下:
……
Façade façade = new Façade();
façade.doAll();
……
第三种情况
主要从安全性的角度考虑。

How Tomcat Works 的书中,第二章的例子。

 

底层调用servlet server 方法时,如此调用:

 

servlet.service((ServletRequest) request, (ServletResponse) response);

 

Request Response 都是实现 ServletResponse 接口的对象。

 

Request Response 又都有自己独有的公共方法 供其他底层框架调用。

 

但是,我们知道,servlet.service( ) 方法实际上是由应用程序员来实现的。应用程序员可以在代码中强制类型转换 ServletRequeat ServletResponse Request Response 对象,进而调用他们独有的方法,这样有安全隐患。

 

所以用到了门面模式:
 
Servlet servlet = null;
      RequestFacade requestFacade = new RequestFacade(request);
      ResponseFacade responseFacade = new ResponseFacade(response); 
      try {
          servlet = (Servlet) myClass.newInstance();
          servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
      } catch(Exception e) {
          System.out.println(e.toString());
      }
 
public class RequestFacade implements ServletRequest {
    private ServletRequest request = null;
    public RequestFacade(Request request) {
        this.request = request;
    }
}
 

在门面中,实现接口,保存一个对象指向Request对象。接口的方法就是简单的调用Request的方法。

 

这样,传给servlet.service( ) 方法的实际上是两个门面。Request对象独有的方法不会出现在 门面对象中,这样就保护了Request对象。
分享到:
评论

相关推荐

    TerryLee的设计模式,手工整理成的word文档,方便学习存档

    11. 外观模式(Façade Pattern):提供一个统一的接口,用来访问子系统中的一组接口。外观模式简化了子系统的使用,客户端只需要与外观交互即可。 12. 享元模式(Flyweight Pattern):用于减少大量相似对象的创建...

    软件设计模式经典案例讲解

    其次,外观模式(Façade Pattern)是结构设计模式,它提供了一个统一的接口,用于简化和封装子系统的复杂性。外观类作为一个协调者,隐藏了子系统内部的复杂交互,使客户端只需要与一个对象进行交互,降低了系统的...

    设计模式解析习题解答,已经做好目录标签

    - 第6章介绍了门面模式(Façade Pattern),它为复杂的子系统提供了一个简单的接口。 - 第7章是适配器模式(Adapter Pattern),允许不同接口的对象协同工作。 - 第9章的策略模式(Strategy Pattern)允许在运行时...

    各种设计模块讲解比较好的几个Blog网页

    “NET设计模式(12):外观模式(Façade Pattern)”属于结构型模式,提供了一个统一的接口,用于访问子系统中的一组接口。它简化了客户端与复杂子系统之间的交互,降低了系统的耦合度。 “NET设计模式(17):...

    Web Service Patterns Java Edition

    3. **Façade Pattern**:提供一个简单的统一接口,隐藏复杂的Web服务接口细节。 4. **Decorator Pattern**:动态地给Web服务添加功能,而不会改变其接口。 5. **Composite Pattern**:将多个Web服务组合成一个更...

    ( [Python.in.Practice(2013.8)].Mark.Summerfield.文字版(英语)

    2.5. Façade Pattern .............................................. 59 2.6. Flyweight Pattern............................................ 64 2.7. Proxy Pattern............................................

    Java中序列化学习笔记/序列和反序列化的实现

    序列化的一个实际应用场景是外观模式(Façade Pattern)。在外观模式中,服务器端创建的外观对象被序列化并通过网络发送给客户端,客户端再进行反序列化。通过控制`serialVersionUID`,服务器端可以强制客户端升级...

    JAVA面试题

    - **Session Façade Pattern**: 使用Session Bean封装对Entity Bean的访问,简化客户端调用过程。 - **Message Façade Pattern**: 用于实现异步消息处理。 - **EJB Command Pattern**: 使用Command Java Beans代替...

    Design Patterns in Java pdf 0分

    ### 外观模式(Façade Pattern) 外观模式提供一个统一的接口,用来访问子系统中的一群接口。它定义了一个高层接口,让子系统更容易使用。 **用途**: - 降低客户端与子系统的耦合度。 - 提供一个简单的接口来...

    ssh框架

    - **业务层**:采用了门面模式(Façade Pattern),提供了一组对外接口,这些接口调用底层的服务组件完成具体的业务逻辑,使得控制层与持久层解耦。 - **持久层**:使用Hibernate进行数据持久化操作,提供了基本...

    23种设计模式趣解.txt

    #### 外观模式(Façade Pattern) 外观模式为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。描述中提到的例子是关于摄影爱好者Nikon想要拍摄照片。虽然...

    EJB系统开发实战录之四

    ### EJB系统开发实战录之四 — Session Bean与Session Façade Design Pattern详解 #### 一、Session Bean概述 在EJB(Enterprise JavaBeans)体系结构中,**Session Bean**扮演着极其重要的角色,它是实现业务...

    PureMVC实现与实践——教程.pdf

    - **Façade的定义**:Façade是PureMVC中一个非常重要的组件,它提供了一个统一的接口,使得开发者可以更方便地与PureMVC的核心层进行交互。 - **创建Façade**:首先需要定义一个Façade类,该类继承自`Facade`...

    Android设计招式之美(1-15章全)_简体中文版

    Android框架與Façade樣式 第 16 章 Android框架之美 ---- Android帶給IT產業的啟示, 375 16.1 Android美何在? 16.2 Android對兩河流域硬體業之意義 16.3 Android對兩河流域軟體業之意義 16.4 Android與「軟硬...

    android设计招式之美

    15.3 Android 框架與Façade 樣式 第 16 章 讓Android 框架之美 ---- Android 帶給IT 產業的啟示, 375 16.1 Android 美何在? 16.2 Android 對兩河流域硬體業之意義 16.3 Android 對兩河流域軟體業之意義 16.4 ...

    Design Pattern Instruction v0.2.ppt

    例如,幻象(Façade)设计模式是一个经常被使用的模式,它提供了一个简单的接口来访问一个复杂的子系统。在没有使用设计模式的情况下,客户端可能需要直接与多个子系统的组件进行交互,这会使得代码变得复杂且难以...

    J2EE设计模式的简洁总结

    例如,在会话 Bean 中调用多个实体 Bean,使用 Façade 会话 Bean 可以提供性能,节省客户端直接调用实体 Bean 的网络开销,解耦分层,利于扩展变化。 四、DTO 模式 DTO 模式或称 VO 模式,是指将数据封装成普通的...

    Programming.in.the.Large.with.Design.Patterns

    Title: Programming in the Large with Design Patterns Author: Eddie Burris Length: 156 pages Edition: 1 Language: English Publisher: Pretty Print Press ...Chapter 10 Façade Chapter 11 Template Method

Global site tag (gtag.js) - Google Analytics