用Java示例进行外观模式教程


本文将重点关注Facade模式。到目前为止,在我们的设计模式中,我们已经看到了Observer Adapter模式。Facade与适配器有一些相似之处,因此这是我们系列中合乎逻辑的下一步。

现实世界中的门面

在现实世界中,门面就在我们周围。操作系统就是一个这样的例子——你看不到你的计算机的所有内部工作,但是操作系统提供了一个使用机器的简化界面。建筑也有立面——建筑的外部。维基百科给了我们软件架构和标准架构之间的一个很好的链接:

在建筑中,从设计的角度来看,建筑的正面通常是最重要的,因为它为建筑的其他部分定下了基调

因此,简而言之,门面旨在使事物看起来更干净、更有吸引力。

设计模式参考卡
关于最流行的设计模式的概述,请访问DZone的Design Patterns Refcard是最好的起点。

门面模式

像适配器模式一样,Facade也被称为结构模式,因为它被用来识别实现实体之间关系的简单方法。“四人帮”关于设计模式的原著中对立面的定义是这样的:

为子系统中的一组接口提供统一的接口。立面定义了一个更高级别的接口,使子系统更容易使用。

Facade模式的图定义非常简单——您真正做的是将客户端与子系统隔离开来:


像适配器模式一样,Facade可以用来隐藏第三方库的内部工作,或者一些遗留代码。客户需要做的只是与门面交互,而不是与它所包含的子系统交互。

下面的序列图说明了客户端如何使用该模式:

 

我将在哪里使用此模式?

由于facade背后的概念是简化接口,面向服务的架构利用了facade模式。例如,在web服务中,一个web服务可能提供对许多较小的服务的访问,这些服务通过外观对调用者是隐藏的。类似地,OSGi捆绑包中的一个典型模式是向捆绑包的用户提供一个接口包。所有其他包对用户都是隐藏的。

那么它在Java中是如何工作的呢?

让我们用一个简单的Java代码来说明这个模式。让我们以一个旅行社网站为例,它允许您预订酒店和航班。我们有一个酒店预订员:

public class HotelBooker{  public ArrayList<Hotel> getHotelNamesFor(Date from, Date to)   {      //returns hotels available in the particular date range  }}

和一个飞行记录员:

public class FlightBooker{  public ArrayList<Flight> getFlightsFor(Date from, Date to)   {      //returns flights available in the particular date range  }}

这两者都有客户了解的酒店和航班数据类型。例如,它们可以在与Facade相同的包中提供。

TravelFacade类允许用户通过一个电话获得他们的酒店和航班信息:

 

public class TravelFacade{   private HotelBooker hotelBooker;   private FlightBooker flightBooker;   public void getFlightsAndHotels(Date from, Data to)  {         ArrayList<Flight> flights = flightBooker.getFlightsFor(from, to);         ArrayList<Hotel> hotels = hotelBooker.getHotelsFor(from, to);         //process and return   }}

客户需要担心的只是Facade类:

public class Client{   public static void main(String[] args)   {        TravelFacade facade = new TravelFacade();         facade.getFlightsAndHotels(from, to);   }}

如您所见,这只是封装数据的一种简单方法。

当心不利的一面

通过在代码中引入Facade,您将把子系统硬连接到Facade中。如果子系统从不改变,这很好,但是如果它改变了,您的Facade可能会被破坏。因此,开发子系统的开发人员应该知道他们代码周围的任何门面。

下一个

下周我们将讨论单例模式。

享受整个“设计模式揭示”系列:

创造模式

结构模式

行为模式