from : http://dev.csdn.net/article/83393.shtm
一、 起因
在看《Ajax in action》的时候,看到它在介绍Adapter和Facade两种模式。由于目前Web开发的特色,特别是客户端Js脚本的开发,需要面对很多的变化和跨平台的挑战,所以,如果应用Adapter和Facade模式,将会非常有益于提高我们软件的可维护性,以及降低总体开发成本。
二、 什么是Adapter和Facade模式
1、 Adapter模式
1.1、定义:
The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
1.2、解释:
Adapter模式所要解决的问题,就是接口不一致的问题。在实际的应用程序中,有的时候客户端(这里指调用方)想要调用的接口与实际上服务端(这里指被调用方)所提供的接口不一致。出现这种情况,我们可能会有两种选择,一种是修改调用方或者被调用方的接口,使之互相适应。另一种就是在调用方和被调用方之间加入一个Adapter,用其连接调用方和被调用方。
在Adapter模式里,Adapter所起的作用,就是一个接口适配器。一个Adapter类会实现(implements)调用方所期待的接口,并且在类中通过委派(delegate)来调用被调用方,从而实现两种不同接口的连接。
1.3、分类:
Adapter模式分为两种实现方式,一种是对象适配器(Object Adapters)和类适配器(Class Adapters)。其中对象适配器(Object Adapters)通过组合(composition)实现,而类适配器(Class Adapters)通过多继承实现。
1.4、关键点:
模式的关键点在于其意图。Adapter模式的意图很明显,就是为了使两个彼此不兼容的接口兼容,使一个本来并不是调用方所期待的接口看起来跟所期待的一样。
在《Head.First.Design.Patterns》这本书里,有一句话可以非常完美并且有趣的描述Adapter模式:
If it walks like a duck and quacks like a duck, then it might be a turkey wrapped with a duck adapter...
2、 Facade模式
2.1、定义:
The Facade Pattern provides a unified interface to a set of interfaces in subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
2.2、解释:
Facade模式的意图也是非常明显。有时候,我们的客户端(调用方)所调用的子系统(subsystem,被调用方)过于复杂。通常,调用方需要连续调用被调用方的N个接口才能完成某种特定的任务。每次调用方重复调用操作都非常繁琐,容易出错,所以本着DRY(Don’t Repeat Yourself)的原则,我们需要提炼出一些经常用到的操作组合成一个接口。这样,每次调用方执行该功能时,仅需要调用该Facade接口,便可以轻松执行某项特定任务。
2.3、作用
Facade模式的作用主要有两点:
1、 为一个太复杂的子系统(subsystem)提供一个统一的、简单的接口共调用方使用。通常需要DRY的接口都是使用率非常高,并且比较复杂的接口。将该接口提取出来,有益于简化工作,并且统一接口名称。
2、 降低系统的耦合度。一批事物的变化率远大于一个事物。应用Facade模式的情景,一般是由于子系统太复杂。当调用方需要执行某些任务时,需要执行一连串操作。而随着子系统的升级,这一连串操作的变化的可能性是非常大的。但是,不管子系统如何变,这一连串操作所提供的功能或者是意义永远不变。所以,Facade模式有利于降低耦合度。
2.4、关键点:
Facade模式的关键点在于,引入Facade模式主要是为了简化和统一接口。Facade模式的接口一般是子系统的一个“快捷方式”。调用方如果还有其他的复杂功能的话,依然可以直接调用子系统的其他接口。
3、 Adapter和Facade模式的区别
模式的区别就在于,要领会其根本的意图。这里有一句话,描述了Adapter和Facade模式以及Decorator模式(这里可以先不管decorator模式)。
An adapter wraps an object to change its interface, a decorator wraps an object to add new behaviors and responsibilities, and a facade "wraps" a set of objects to simplify.
三、 Web开发所面临的问题
Ajax时代的Web开发,有一个共同的特点。由于此时的浏览器端应用再也不是传统的简单页面,而变成了复杂的JavaScript客户端应用程序。所以,随着代码量的上升,要求我们用更加合乎软工的方式去看待Ajax应用程序。如果在此时能够引入各种OO原则及模式,将会提高Ajax应用程序的整体质量。
目前在浏览器端进行JavaScript开发时,主要会面临这么两种问题:
1、 目前的Web开发还比较混乱。各种浏览器对W3C标准的支持都有问题,并不统一。进行Web开发时,尽管我们一直提倡基于Web标准进行开发,但有时我们往往有些力不从心。
2、 Web开发过程中所使用的各种浏览器API,其本身组合的也并不足够合理。有时候为了执行某项操作,我们需要连续操作很多接口。而实际上,在大多数情况下,我们都没必要这么DRY(Do Repeat Yourself).
你可以看到,其实上面两种情况就分别对应于设计模式中的Adapter和Façade两种模式的需求。那么,下面让我们看看如何在实际的代码中应用上述两种模式解决问题?
四、 如何应用Adapter和Facade模式?
在《Ajax in action》中,同样有一段代码,体现了这样的需求。我把它修改了一下,大家看看,能否从中找出Adapter和Facade模式的影子?
CGIAJAX.util["STATICS"] = {};
CGIAJAX.util.STATICS.READY_STATE_UNINITIALIZED=0;//constant
CGIAJAX.util.STATICS.READY_STATE_LOADING=1;
CGIAJAX.util.STATICS.READY_STATE_LOADED=2;
CGIAJAX.util.STATICS.READY_STATE_INTERACTIVE=3;
CGIAJAX.util.STATICS.READY_STATE_COMPLETE=4;
CGIAJAX.util.ContentLoader = function(url, onload, method, msgBody, onerror)//constructor, contains all attributes
{
this.url=url;
this.onload=onload;
this.method = (method) ? method : "GET";//default value of method is GET
this.msgBody = (msgBody) ? msgBody : null;//default value of message body send to server
this.onerror=(onerror) ? onerror : this.defaultError;//default method to handle error
this.req=null;
}
//contains all method
CGIAJAX.util.ContentLoader.prototype=
{
loadXMLDoc:function()//send request to server to get response
{
if (window.XMLHttpRequest)
{
this.req=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
this.req=new ActiveXObject("Microsoft.XMLHTTP");
}
if (this.req)
{
try
{
var loader=this;
this.req.onreadystatechange=function()
{
loader.onReadyState.call(loader);
}
if ("GET" == this.method)
{
this.req.open('GET',this.url,true);
this.req.send(null);
}
else
{
if (!this.msgBody)
{
this.onerror.call(this);
}
this.req.open(this.method,this.url,true);
this.req.send(this.msgBody);
}
}
catch (err)
{
this.onerror.call(this);
}
}
},
onReadyState:function()
{
var req=this.req;
var ready=req.readyState;
if (ready==CGIAJAX.util.STATICS.READY_STATE_COMPLETE)
{
var httpStatus=req.status;
if (httpStatus==200 || httpStatus==0)
{
this.onload.call(this);
}
else
{
this.onerror.call(this);
}
}
},
defaultError:function()//default error handler
{
alert("error fetching data!"
+"\n\nreadyState:"+this.req.readyState
+"\nstatus: "+this.req.status
+"\nheaders: "+this.req.getAllResponseHeaders());
}
};
怎么样,看到了吗?没有?那好,让我来解释一下这段代码如何应用Adapter和Facade模式的。当然,这里并不分析具体代码的含义了。
1、 Adapter模式
在Ajax应用中经常用到的XHR(xmlHttpRequest)对象,就是需要Adapter模式的一个很好的例子。
XHR对象非W3C标准,所以,尽管现有的较新的浏览器都支持XHR对象,但其具体实现是不一致的。在微软的IE里,XHR是以“ActiveXObject”的样式实现的。而在mozilla浏览器里,其又以一种build-in对象的形式实现。天知道在其他的什么浏览器或者日后的日子里,这种实现方式会不会发生变化。
而对于我们常用的应用程序来说,我们并不关心这些所有的细节。我们所需要知道的,就是当我们希望创建一个XHR对象时,有一个XHR对象会被创建,并且供我们使用。至于究竟如何创建,我们对它并不关心。所以,你可以看到,在上面的代码里,我们是通过在ContentLoader类的loadXMLDoc的方法中实现的。
if (window.XMLHttpRequest)
{
this.req=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
this.req=new ActiveXObject("Microsoft.XMLHTTP");
}
这里的一个IF语句帮助我们实现了跨平台性,它便是一个Adapter。在这里,我们通过一点来自动适应各种平台的变化。我们的程序代码期待一个统一的创建XHR的接口。这段代码实现了这个接口,并且通过委托(delegate)的机制,自动帮我们用各种方法在各种不同的平台下实例化一个XHR对象。
想象一下,在不远的未来,有一种Xbrower出现,并且非常红火,值得我们兼容。我们只要改变我们的Adapter,就可以适应该变化。而我们其他的客户端代码都不需要修改,岂不很好吗?
2、 Facade模式
当你需要用XHR对象向服务器请求数据的时候,你总是会很痛苦的执行一连串操作,仅仅是为了请求一次数据:
1、 建立XHR对象
2、 注册callback函数
3、 用open方法设置请求方式,地址,模式
4、 用send发送请求
5、 监视请求的状态,当达到某一特定状态时,执行某项特殊功能。。。
天,好复杂,可是为什么我们要不断地重复自己呢?
上面的ContentLoader类就可以很好的屏蔽这些复杂性。当你想要从服务器端获得一些数据的时候,你关心的是服务器端的数据,而不是这整个复杂的过程。通过应用上面的这个ContentLoader类,你可以很轻松的用两行代码就获得数据。
var myRequest = new CGIAJAX.util.ContentLoader(url, refreshTalbe);
myRequest.loadXMLDoc();
可以看到,实际上ContentLoader类就是一个简单的接口,它将整个复杂的接口简单化、统一化。如此一来,我们就可以DRY了。当然,ContentLoader类并不会使我们的灵活性有所降低。如果你需要的话,你还是可以直接调用浏览器所提供的XHR接口的。可是大多数时候,我们只需要用ContentLoader类就可以很好的完成任务了。
再想象一下。假如说未来W3C将XHR作为标准,并且扩充了XHR接口的功能,那么我们怎么办?很可能扩充功能的代价就是接口的变化或者接口调用顺序的变化。如果我们没有应用Facade模式,我们会怎样?逐个修改代码中每一个用到XHR的地方?知道一切运转起来看似没有问题?或者我们现在就应用Facade模式,到时候,我们就可以轻松的修改一下Facade模式所涉及的接口内容,然后跑去看NBA了,不是吗?
五、 警惕Ajax开发!
为何要警惕Ajax开发?
众所周知,由于Ajax导致Web开发模式上的变化,将会导致客户端代码的激增,由量变变成质变。而且最重要的是,Ajax现在所用到的各种技术,很大一部分都还没有成为标准,或者刚刚成为标准。这就意味着,这些东西会在未来的一段时间内,频繁变化。如果我们应用程序设计时,对该方面的变化有所准备,那么到头来痛苦的只有我们自己。
在Ajax开发中应用OO模式以及OO原则,最重要的并不是炫耀某种技术,而是期望这种已被证明的强大技术能够为我们的开发带来根本上的好处。
==============自己的理解==================
Adaptor 适配器模式
就像一个翻译,一个中间人,解决两个接口的矛盾,让对方互相理解自己的意思。
Facade 门面模式
将重复用到的方法封装到一个接口,用到的时候每次调用这个接口。如果需要修改,也仅仅是修改接口这一个地方。
分享到:
相关推荐
本文将深入探讨FACADE模式、Adapter模式以及Singleton和Proxy模式的基本概念、应用场景和关键要素。 首先,FACADE(外观)模式是一种接口型模式,它的主要作用是为复杂的子系统提供一个简单的接口,使得客户端无需...
**Facade模式在Ajax中的应用** 在AjaxDemo中,我们可以看到Facade模式的实现。通常,这个Demo会包含一个或多个JavaScript文件,其中一个作为Facade,对外暴露简单的接口,用于发起Ajax请求。例如,我们可以有一个名...
总结来说,Facade模式在Java中的应用有助于降低系统的复杂性,提供一个更简洁的接口,使客户端代码更易理解和维护。通过将子系统的复杂细节隐藏在门面之后,我们能够更容易地扩展或修改子系统,而不影响到客户端代码...
设计模式之门面模式(Facade模式),介绍门面模式,实际例子分析,代码讲解等
**C++ Facade模式** Facade模式,又称为外观...总之,C++中的Facade模式是一种非常实用的设计模式,尤其在处理复杂系统时,它可以有效地隐藏子系统的复杂性,提供一个简单易用的接口,提高系统的可维护性和可扩展性。
在实际应用中,Facade模式常见于各种工具库和框架。例如,在Java的Swing库中,`JFrame`类就是一个Facade,它封装了许多复杂的窗口组件和事件处理逻辑,使得开发者可以更简单地创建用户界面。 源码中的应用: 在Java...
`Facade`模式则广泛应用于系统集成、框架设计等场景,比如Spring框架中的`ApplicationContext`就是典型的`Facade`,它对外提供了一系列方法来管理Bean的生命周期和依赖注入。 总的来说,`Command`模式和`Facade`...
**外观(Facade)模式**是一种结构型设计模式,它的主要目的是提供一个统一的接口,用于客户端访问复杂的...在实际开发中,我们经常可以在各种软件框架和库中看到`Facade`模式的应用,如网络通信库、图形用户界面库等。
Facade设计模式在VB数据库中的应用
### JAVA设计模式在JDK中的应用 #### 一、引言 在软件开发过程中,设计模式作为一套被广泛接受的解决方案,能够帮助开发者解决常见的设计问题。Java作为一门流行的编程语言,其标准库(JDK)中巧妙地融入了多种设计...
提出了一种优化模式的多层架构体系,详细分析了Pet Shop的典型三层架构及使用的Factory模式、Duwamish的多层架构及使用的Facade模式,比较两者不足,综合各自优势,提出目标系统开发架构,更侧重于优化架构的设计、...
在《C++设计模式全总结-通俗易懂》这一资源中,作者通过使用C++语言详细解析了GoF所提出的23种设计模式,并附带了相应的实现源码。这份资料不仅适合初学者入门学习,也适合有一定基础的开发者深入研究。 #### 创建...
在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要资源分。敬请期待。 这是第11节:结构型...
在实际应用中,Facade和Simple Factory模式经常结合使用。例如,你可能有一个复杂的系统,由多个组件(每个组件代表一个类)组成,这些组件可能有自己的创建逻辑。在这种情况下,你可以使用Simple Factory来创建这些...
外观模式(Facade Pattern)是设计模式中的一种结构型模式,主要目的是为了解决复杂的系统接口问题,提供一个简单的统一入口,使得客户端可以更方便地使用系统。在Java中,外观模式通常用来隐藏系统的复杂性,对外只...
在实际应用中,比如在软件开发框架中,如Spring Framework,就大量使用了外观模式,提供了IoC容器作为对外的统一接口,用户可以通过这个接口轻松地管理各种bean和依赖关系,而无需关心底层的实现细节。 综上所述,...
文章通过具体的例子和代码展示了如何在实际开发中运用这一模式,并解释了它与其他几种设计模式的区别。 #### 二、系统复杂度及动机 在开发大型或复杂的系统时,我们经常会遇到由多个子系统组成的系统结构。例如,...
Schmidt教授在其论文《Wrapper Facade》中的描述,`Facade设计模式`的意图是“封装低级别的函数和数据结构,在更简洁、健壮、可移植和易于维护的高级面向对象类接口中”。 #### 四、设计模式的应用场景 - **网络...