您的位置:首页 > Web前端 > JavaScript

4. JavaScript 设计模式(适配器模式,外观模式)

2017-05-31 11:20 246 查看
1. 适配器模式

什么是适配器。其实生活中都很多例子:例如插头和插座,插座是三角的,但是插头是二字行的插头,这时候我们经常会使用插头的转换器。其实这个就是适配器。还有其他的例子,例如安卓手机充电的时候的插头和苹果手机的插头,他们都可以用usb转换和插头连接。

将一个类的接口,转换成客户期望的另一个接口。适配器让原来接口不兼容的类可以合作无间。



看看下面的例子:

如果一个火鸡走起路来像只鸭子,叫起来像只鸭子,那么他可能是一只包装了鸭子适配器的火鸡。(看代码你就懂了。)

//鸭子
var Duck = function(){

};
Duck.prototype.fly = function(){
throw new Error("该方法必须被重写!");
};
Duck.prototype.quack = function(){
throw new Error("该方法必须被重写!");
}

//火鸡
var Turkey = function(){

};
Turkey.prototype.fly = function(){
throw new Error(" 该方法必须被重写 !");
};
Turkey.prototype.gobble = function(){
throw new Error(" 该方法必须被重写 !");
};

//鸭子
var MallardDuck = function () {
Duck.apply(this);
};
MallardDuck.prototype = new Duck(); //原型是Duck
MallardDuck.prototype.fly = function () {
console.log("可以飞翔很长的距离!");
};
MallardDuck.prototype.quack = function () {
console.log("嘎嘎!嘎嘎!");
};

//火鸡
var WildTurkey = function () {
Turkey.apply(this);
};
WildTurkey.prototype = new Turkey(); //原型是Turkey
WildTurkey.prototype.fly = function () {
console.log("飞翔的距离貌似有点短!");
};
WildTurkey.prototype.gobble = function () {
console.log("咯咯!咯咯!");
};

// 包装火鸡用的鸭子适配器
var TurkeyAdapter = function(oTurkey){
Duck.apply(this);
this.oTurkey = oTurkey;
};
TurkeyAdapter.prototype = new Duck();
TurkeyAdapter.prototype.quack = function(){
this.oTurkey.gobble();
};
TurkeyAdapter.prototype.fly = function(){
var nFly = 0;
var nLenFly = 5;
for(; nFly < nLenFly;){
this.oTurkey.fly();
nFly = nFly + 1;
}
};

var oMallardDuck = new MallardDuck();
var oWildTurkey = new WildTurkey();
var oTurkeyAdapter = new TurkeyAdapter(oWildTurkey);

//原有的鸭子行为
oMallardDuck.fly();
oMallardDuck.quack();

//原有的火鸡行为
oWildTurkey.fly();
oWildTurkey.gobble();

//适配器火鸡的行为(火鸡调用鸭子的方法名称)
oTurkeyAdapter.fly();
oTurkeyAdapter.quack();


从上面的代码可见,使用适配器的过程如下:

客户通过目标接口调用适配器的方法对适配器发出请求

适配器使用被适配者接口把请求转换成被适配者的一个或多个调用接口

客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用

4.外观模式

现在看看另一个改变接口的新模式,但是他改变接口的原因是为了简化接口。这个模式被巧妙地命名为外观模式(Facade-Pattern)。

提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。

外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦。外观模式经常被认为开发者必备,它可以将一些复杂操作封装起来,并创建一个简单的接口用于调用。

外观模式经常被用于JavaScript类库里,通过它封装一些接口用于兼容多浏览器,外观模式可以让我们间接调用子系统,从而避免因直接访问子系统而产生不必要的错误。

外观模式的优势是易于使用,而且本身也比较轻量级。但也有缺点 外观模式被开发者连续使用时会产生一定的性能问题,因为在每次调用时都要检测功能的可用性。

举个例子,对于不同的浏览器,添加事件的方法也不是一样的。而可以使用外观模式通过检测浏览器特性的方式来创建一个跨浏览器的使用方法。

var addMyEvent = function (el, ev, fn) {
if (el.addEventListener) {
el.addEventListener(ev, fn, false);
} else if (el.attachEvent) {
el.attachEvent('on' + ev, fn);
} else {
el['on' + ev] = fn;
}
};


那么何时使用外观模式呢?一般来说分三个阶段:

首先,在设计初期,应该要有意识地将不同的两个层分离,比如经典的三层结构,在数据访问层和业务逻辑层、业务逻辑层和表示层之间建立外观Facade。

其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。

第三,在维护一个遗留的大型系统时,可能这个系统已经很难维护了,这时候使用外观Facade也是非常合适的,为系系统开发一个外观Facade类,为设计粗糙和高度复杂的遗留代码提供比较清晰的接口,让新系统和Facade对象交互,Facade与遗留代码交互所有的复杂工作。

参考:大话设计模式

外观模式模式转载来自:http://www.cnblogs.com/TomXu/archive/2012/02/28/2353448.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息