Facade设计模式

来源:百度文库 编辑:神马文学网 时间:2024/03/29 15:56:29
我曾经以外聘开发人员身份为一家大型设计和制造公司工作。我上班的第一天,项目的技术负责人没有到。客户当然不愿意在按小时付工资的情况下,我却无事可做。他们想让我干点什么,就算没多大用处!你是否也有过这样的经历?
于是,一位项目成员给我找了些事情。她说:“你肯定要学习我们有时会用到的CAD/CAM 系统,所以最好现在就开始。从那边的手册开始好了。”然后她带我走到一堆文档前。我可绝没有夸大其词:我要读的手册足有8英尺厚,每页都是8.5×11英寸,而且都用小字印刷!这可真是一个复杂的系统!

图6-1  8英尺厚的手册=一个复杂的系统!
现在,如果你、我还有其他四五个人共同开发一个需要使用该系统的项目,应该采用哪一种方式呢?是我们都学习这个系统呢,还是我们抽签决定,输的人负责编写例程,供其他人用来与系统接口?
输的人应该决定,我和团队中的其他人如何使用系统,什么样的应用程序编程接口(API)最适合我们的特殊需要。然后我和程序设计社区的其他人就都能够使用这个新的接口,而无需了解整个复杂的系统了(参见图6-2)。
这种方法在只使用系统的一部分功能,或者在以特殊方式与系统交互时才有效。如果系统的所有功能都需要使用,那么除非最初的设计很糟,否则并无余地对设计进行改进。
这就是Facade模式(见图6-3)。通过这个模式我们能够更容易地使用一个复杂的系统,要么只使用系统的一部分功能,要么是以特殊方式使用系统。这里我们的系统就很复杂,但我们只需要使用一部分功能。因此,我们最后得到了一个更简单、更容易使用,或者说按我们的需要量身订做的系统。

图6-2  将客户与子系统隔离开来
大多数工作还是需要由底层系统完成。Facade模式提供了一组容易理解的方法,这些方法使用底层系统来实现新定义的函数。
Facade模式:关键特征
意图           希望简化原有系统的使用方式。需要定义自己的接口。
问题           只需要使用某个复杂系统的子集,或者,需要以一种特殊的方式与系统交互。
解决方案   Facade为原有系统的客户提供了一个新的接口。
参与者与协作者        为客户提供的一个简化接口,使系统更容易使用。
效果           Facade模式简化了对所需子系统的使用过程。但是,由于Facade并不完整,因此客户可能无法使用某些功能。
实现
定义一个(或多个)具备所需接口的新类。
让新的类使用原有的系统。

图6-3  Facade模式的通用结构图
Facade不仅可以用来通过方法调用创建更简单的接口,还能用来减少客户必须处理的对象数量。例如,假设有一个Client对象必须处理Database、Model、Element对象。Client必须首先通过Database对象打开数据库,获取Model对象,然后再查询Model对象,获取Element对象,最后请求Element对象的信息。如果能够创建一个可供Client查询的Database Facade,那么以上过程将容易得多(参见图6-4)。

如果Facade能够设计成无状态的(也就是说,其中没有存储状态),则一个Facade对象就能够被多个其他对象使用。在后面的第21章中,我将讲述如何实现这一点,其中用到了Singleton模式和Double-Checked Locking模式。
假设除了使用系统中原有功能之外,我还需要提供一些新功能——比如,记录对特定例程的所有调用。这种情况下,就不仅仅是使用系统的部分功能了。
这时,我为Facade类所写的方法中可以为新的功能增加一些新例程。这仍然是Facade模式,但是增加了新的功能。我认为其主要目的是简化,因为我不想强制客户例程知道它还需要调用额外的例程——让Facade去做好了。
Facade模式提出了一种通用方法;它为我提供了起点。这个模式的Facade部分实际上就是创建了一个新的接口供客户使用,来代替系统的原有接口。我之所以能够这样做,是因为Client对象并不需要原系统提供的所有功能。
模式提出了通用方法
模式只是提出了通用方法。是否增加新的功能应根据具体情况而定。模式只是可以作为起点的蓝图,可不能完全原样照搬。
Facade模式还可以用来隐藏或者封装系统。Facade类能够将系统作为自己的私有成员包含进来。在此情况下,原系统将与Facade类联系起来,但Facade类的客户无需看到。
封装系统的原因很多,包括:
● 跟踪系统的使用情况——通过强制所有对系统的访问都必须经过 Facade,可以很容易地监视系统的使用情况。
● 改换系统——未来可能需要切换系统。通过将原系统作为 Facade 类的一个私有成员,可以最省力地将切换到新的系统。当然,可能还要做很多工作,但是至少我只需在一个地方修改代码(Facade类)就行了。