本文将重点关注Facade模式。到目前为止,在我们的设计模式中,我们已经看到了Observer 和Adapter模式。Facade与适配器有一些相似之处,因此这是我们系列中合乎逻辑的下一步。
在现实世界中,门面就在我们周围。操作系统就是一个这样的例子——你看不到你的计算机的所有内部工作,但是操作系统提供了一个使用机器的简化界面。建筑也有立面——建筑的外部。维基百科给了我们软件架构和标准架构之间的一个很好的链接:
在建筑中,从设计的角度来看,建筑的正面通常是最重要的,因为它为建筑的其他部分定下了基调因此,简而言之,门面旨在使事物看起来更干净、更有吸引力。
设计模式参考卡
关于最流行的设计模式的概述,请访问DZone的Design Patterns Refcard是最好的起点。
像适配器模式一样,Facade也被称为结构模式,因为它被用来识别实现实体之间关系的简单方法。“四人帮”关于设计模式的原著中对立面的定义是这样的:
为子系统中的一组接口提供统一的接口。立面定义了一个更高级别的接口,使子系统更容易使用。
Facade模式的图定义非常简单——您真正做的是将客户端与子系统隔离开来:
像适配器模式一样,Facade可以用来隐藏第三方库的内部工作,或者一些遗留代码。客户需要做的只是与门面交互,而不是与它所包含的子系统交互。
下面的序列图说明了客户端如何使用该模式:
由于facade背后的概念是简化接口,面向服务的架构利用了facade模式。例如,在web服务中,一个web服务可能提供对许多较小的服务的访问,这些服务通过外观对调用者是隐藏的。类似地,OSGi捆绑包中的一个典型模式是向捆绑包的用户提供一个接口包。所有其他包对用户都是隐藏的。
让我们用一个简单的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可能会被破坏。因此,开发子系统的开发人员应该知道他们代码周围的任何门面。
下周我们将讨论单例模式。