`
newleague
  • 浏览: 1504719 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

门面模式-《java与模式》

阅读更多

1、医院的例子

 

                病人             病人           病人

 

                     \             |            /

                       

                               接  待  员

 

                       /                          \

 

               门 诊               ---          挂 号

 

                      |                              |

 

                划 价              ---          取  药

 

(少了两条线:接待员分别到划价和取药)

 

 

 

 

随着系统的不断改进和开发,它们会变得越来越复杂,系统会生成大量的类,这使得程序流程更难被理解。门面模式可为这些类提供一个简化的接口,从而简化访问这些类的复杂性,有时这种简化可能降低访问这些底层类的灵活性,但除了要求特别苛刻的客户端之外,它通常都可以提供所需的全部功能,当然,那些苛刻的用户仍然可以直接访问底层的类和方法。

门面模式(Facade)也被称为正面模式、外观模式,这种模式用于将一组复杂的类包装到一个简单的外部接口中。

现在考虑这样的场景:我们有一个顾客需要到饭店用餐,这就需要定义一个Customer类,并为该类定义一个haveDinner()方法。考虑该饭店有三个部分:收银部、厨师部和服务生部,用户就餐需要这三个部门协调才能完成。

本示例程序先定义一个收银部,用户需要调用该部门的pay()方法来支付用餐费。

程序清单:codes\09\9.3\Facade\PaymentImpl.java

public class PaymentImpl
implements Payment
{
//模拟顾客支付费用的方法
public String pay()
{
String food = "快餐";
System.out.println("你已经向收银员支付了费用,您购买的食物是:"
+ food);
return food;
}
}

程序接下来要定义一个厨师部门,用户需要调用该部门的cook ()方法来烹调食物。

程序清单:codes\09\9.3\Facade\CookImpl.java

public class CookImpl
implements Cook
{
//模拟烹调食物的方法
public String cook(String food)
{
System.out.println("厨师正在烹调:" + food);
return food;
}
}

程序还要定义一个服务生部门,用户需要调用该部门的serve ()方法来得到食物。

程序清单:codes\09\9.3\Facade\WaiterImpl.java

public class WaiterImpl
implements Waiter
{
//模拟服务员上菜的方法
public void serve(String food)
{
System.out.println("服务器员已将" + food
+ "端过来了,请慢用...");
}
}

接下来实现Customer类的haveDinner()方法时,系统将有如下代码实现。

程序清单:codes\09\9.3\Facade\Customer.java

public class Customer
{
public void haveDinner()
{
//依次创建三个部门实例
Payment pay = new PaymentImpl();
Cook cook = new CookImpl();
Waiter waiter = new WaiterImpl();
//依次调用三个部门实例的方法来实现用餐功能
String food = pay.pay();
food = cook.cook(food);
waiter.serve(food);
}
}

正如上面粗体字代码所示,Customer需要依次调用三个部门的方法才可实现这个havaDinner()方法。实际上,如果这个饭店有更多的部门,那么程序就需要调用更多部门的方法来实现这个haveDinner()方法——这就会增加haveDinner()方法的实现难度了。

 

 

为了解决这个问题,我们可以为Payment、Cook、Waiter三个部门提供一个门面(Facade),使用该Facade来包装这些类,对外提供一个简单的访问方法。下面是该Facade类的代码。

程序清单:codes\09\9.3\Facade\Facade.java

public class Facade
{
//定义被Facade封装的三个部门
Payment pay;
Cook cook;
Waiter waiter;
//构造器
public Facade()
{
Payment pay = new PaymentImpl();
Cook cook = new CookImpl();
Waiter waiter = new WaiterImpl();
}
public void serveFood()
{
//依次调用三个部门的方法,封装成一个serveFood()方法
String food = pay.pay();
food = cook.cook(food);
waiter.serve(food);
}
}

从Facade代码可以看出,该门面类保证了Payment、Cook、Waiter三个部门,程序的粗体字代码对外提供了一个简单的serveFood()方法,该方法对外提供了一个用餐的方法,而底层则依赖于三个部门的pay()、cook()、serve()三个方法。

一旦程序提供了这个门面类Facade之后,Cutsomer类实现havaDinner()方法就变得更加简单了。下面是通过Facade类实现haveDinner()方法的代码。

public void haveDinner()
{
//直接依赖于Facade类来实现用餐方法
Facade f = new Facade();
f.serveFood();
}

从上面程序可以看出,如果不采用门面模式,客户端需要自行决定需要调用哪些类、哪些方法,并需要按合理的顺序来调用它们才可实现所需的功能。不采用门面模式时,程序有如图9.8所示的结构。

 
图9.8  未使用门面模式的结构图

从图9.8中可以看出,两个客户端需要和底层各对象形成错综复杂的网络调用,无疑增加了客户端编程的复杂度。使用正面模式后的程序结构如图9.9所示。

从图9.9可以看出,当程序使用了门面模式之后,客户端代码只需要和门面类进行交互,客户端代码变得极为简单。

 
图9.9  使用门面模式的程序结构图

阅读到此处相信读者对Spring的HibernateTemplate类有点感觉了,当我们的程序使用HibernateTemplate的find()方法时,程序只要此一行代码即可得到查询返回的List。但实际上该find()方法后隐藏了如下代码:

Session session = sf.openSession();
Query query = session.createQuery(hql);
for(int i = 0 ; i < args.length ; i++)
{
query.setParameter(i , Object val)
}
query.list();

因此,我们可以认为HibernateTemplate是SessionFactory、Session、Query等类的门面,当客户端程序需要进行持久化查询时,程序无须调用这些类,而是直接调用HibernateTemplate门面类的方法即可。

除此之外,Java EE应用里使用业务逻辑组件来封装DAO组件也是典型的门面模式——每个业务逻辑组件都是众多DAO组件的门面,系统的控制器类无须直接访问DAO组件,而是由业务逻辑方法来组合多个DAO方法以完成所需功能,而Action只需与业务逻辑组件交互即可。在这种设计方式下,Java EE应用的各组件有如图9.10所示的结构图。

 
图9.10  Java EE应用结构图
分享到:
评论

相关推荐

    java模式-java中的所有模式-java进阶必备···

    ### Java设计模式详解 #### 一、创建型模式 **1. 工厂方法模式(Factory Method)** - **定义**:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 - **应用场景*...

    23种模式详解-java附详细文档

    Java作为广泛应用的编程语言,其设计模式的理解与应用是开发者必须掌握的关键技能之一。"23种模式详解-java附详细文档"的资源正是为了帮助学习者深入理解这23个经典的设计模式。下面,我们将详细探讨这些设计模式...

    设计模式之门面模式Java实现和类设计图

    在Java中,我们可以用以下方式实现门面模式: 1. **定义子系统接口**: 首先,我们需要定义子系统中的组件接口。这些接口通常代表了子系统的一部分功能。例如,假设我们有一个复杂的系统由三个组件组成:`...

    Java教程-Java设计模式之中介者模式.pdf

    - **与门面模式(Facade)**:门面模式是为子系统提供一个统一的入口,简化客户端与子系统的交互,而中介者模式是解决子系统内部对象间的通信问题。 4. **优缺点** - **优点**:降低对象之间的耦合度,提高系统的...

    IT面试-Java设计模式介绍

    Java设计模式是面向对象编程中的一种最佳实践,用于解决软件设计中反复出现的问题,提高代码的可重用性、灵活性和可维护性。设计模式源于建筑领域的理论,由Erich Gamma等人将其引入到计算机科学中,至今已知的有23...

    Java 经典设计模式讲解以及项目实战

    Java 经典设计模式讲解以及项目实战 设计模式简介:主要介绍各种设计模式的概念和运用场景等 设计模式综合运用:主要是笔者在实际工作中运用到的一些设计模式综合运用事例的提炼 Spring设计模式简介:主要是讲述...

    JAVA设计模式-设计模式公司出品

    这本书不仅讲解了具体的模式,还提供了与之相关的Java实现代码示例,使得程序员可以将理论应用到实际开发中。对于不同水平的程序员来说,这本书都能够提供很大的帮助。初级程序员可以学习设计模式的基本概念和应用,...

    2--java的23种设计模式.ppt

    Java的23种设计模式是软件开发中常用的设计原则,它们可以帮助我们编写可维护、可扩展和可重用的代码。这些模式分为三大类:创建型模式、结构型模式和行为型模式。 创建型模式主要关注对象的创建,包括5种模式: 1...

    Java实现的门面模式

    在Java中,门面模式的应用可以帮助我们更好地组织代码,降低系统的耦合度,提高代码的可读性和可维护性。下面将详细介绍门面模式的概念、结构和实现方式。 门面模式的核心思想是为子系统提供一个统一的接口,这个...

    java 设计模式-个人总结

    ### Java设计模式——个人总结 #### 一、概述 本文档总结了常见的Java设计模式及其应用,涵盖了十种经典的设计模式,并提供了相应的代码示例。这些设计模式旨在解决软件开发过程中遇到的一系列常见问题,帮助...

    java设计模式

    22.4.1 Java世界中的观察者模式 22.4.2 项目中真实观察者模式 22.4.3 订阅发布模型 22.5 最佳实践 第23章 门面模式 23.1 我要投递信件 23.2 门面模式的定义 23.3 门面模式的应用 23.3.1 门面模式的优点 23.3.2 门面...

    JAVA设计模式(门面模式)—视频

    外部与一个子系统的通信必须通过一个统一的门面对象进行。这就是门面模式。 门面模式的结构 涉及两个角色: 门面角色:客户端可以调用这个角色的方法。此角色知道子系统的功能和责任。在正常情况下,本角色会将...

    设计模式java 版本

    12. **门面模式**:为子系统提供一个统一的入口,简化系统接口。与外观模式类似,但更强调对子系统组件的封装。 13. **职责链模式**:将请求的发送者和接收者解耦,一个对象只需定义它能处理的请求,将请求传递给下...

    设计模式 (Java描述)

    ##### 第7章:门面模式(Facade Pattern) - **定义**:为子系统中的一组接口提供一个一致的界面,本模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 - **目的**:简化复杂的系统接口。 - **应用...

    23种设计模式的实现(Java 版),java设计模式

    例如,工厂模式常用于对象的创建,单例模式用于管理共享资源,门面模式用于简化复杂的子系统,代理模式用于控制访问,适配器模式则用于不同接口之间的转换,组合模式和装饰器模式则提供了在运行时动态地添加或修改...

    java门面模式,简单入门

    在Java中,门面模式经常用于简化对系统的调用,提高代码的可读性和可维护性。 门面模式的核心结构包括三个部分:门面(Facade)、子系统(Subsystems)和客户端(Client)。下面将详细介绍这些组成部分以及它们在...

    设计模式Java版

    以下是针对"设计模式Java版"的详细解释: 1. **单例模式**:确保一个类只有一个实例,并提供全局访问点。在Java中,通常通过双重检查锁定(Double-Checked Locking)或静态内部类等方式实现。 2. **工厂模式**:...

Global site tag (gtag.js) - Google Analytics