本文参考于:
设计模式课程
设计模式之适配器模式

设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每种模式在现实中都有相应的原理来与之对应,每种模式都描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是设计模式能被广泛应用的原因。

设计模式如此强大,从今天开始,抓住大学生活的尾巴,我要一天学习一个设计模式啦。

第一个设计模式是:适配器模式

使用场景:
1 系统需要使用现有的类,而这些类的接口不符合系统的需要。
2 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
3 需要一个统一的输出接口,而输入端的类型不可预知。
比如插座-充电器-电子设备的例子。插座输出的是220V的电压,而电子设备充电时只需5V,不然就note7了,这时充电器充当适配器,接受插座的220V,输出5V,从而作为连接器让电子设备顺利充电。
总的来说适配器就是src-adapter-dist的模式,与修饰模式直接无感使用src不同,适配器模式使用对象变为adapter。
适配器模式不是在系统设计时所预期的,是在需求改动、升级的时候动态添加的,如果一个系统使用过多的适配器,明明调用的是A接口,却在适配器内部实现的是调用B接口,导致系统混乱。

适配器模式分为三种:
一、类适配器模式;二、对象适配器模式;三、接口适配器模式(JS没有抽象类的概念,这里不详细讲述)

接下来举的例子就是上面插座-充电器-电子设备的例子。

类适配器

继承src,实现dist的接口。
先是插座

function Plug() {
    this.V = 220;
}
Plug.prototype.outputVoltage220 = function() {
    return this.V;
};

再是手机

function Phone() {
    this.V = 5;
}
Phone.prototype.charge = function(outputDevice) {
    if (outputDevice.outputVoltage5() === this.V) {
        console.log('充电中...');
    } else {
        console.log('充电异常');
    }
};

现在我们要实现的是outputVoltage5的接口,以对接手机的输入电压

function inherit(Sub, Sup) {
    Sub.prototype = Object.create(Sup.prototype);
    Object.defineProperty(Sub.prototype, 'constructor', {
        enumerable: false,
        value: Sub
    });
}

function Charger() {
    Plug.call(this);
}
inherit(Charger, Plug);
Charger.prototype.outputVoltage5 = function() {
    return this.outputVoltage220() / 44;
};

这样充电器就实现了连接插座和手机的功能。

var cg = new Charger();
var mobile = new Phone();
mobile.charge(cg);

小结:类适配器使用继承的方式实现,会暴露src的所有其他方法。

对象适配器

对象适配器和类适配器相差不大,使用组合的方式实现。
持有src,实现dist接口,完成src->dist的适配

function Charger2() {
    this.plug = null;
}
Charger2.prototype.initPlug = function(plug) {
    return this.plug = plug;
};
Charger2.prototype.outputVoltage5 = function() {
    if (!this.plug) {
        console.error('未插电');
        return -1;
    }
    return this.plug.outputVoltage220() / 44;
};

同样也能正常充电

var plug = new Plug();
var cg2 = new Charger2();
cg2.initPlug(plug);
mobile.charge(cg2);

小结:根据合成复用原则,组合优于继承,所以结构型模式一般都是对象结构型模式。

以上表述有什么问题,欢迎大家指出,一起学习。


一画先生
83 声望12 粉丝

我司长期招聘前端开发工程师,有意的小伙伴+vx: Mr_yihua