美文网首页JavaScript
16种JavaScript设计模式(下)

16种JavaScript设计模式(下)

作者: 嘿哟写bug呢 | 来源:发表于2020-04-08 12:45 被阅读0次

    ## 简介

    紧接[上文(地址)](https://www.jianshu.com/p/993027963b60),我们继续介绍以下几种设计模式

    * 模板方法模式

    * 享元模式

    * 责任链模式

    * 中介者模式

    * 装饰者模式

    * 状态模式

    * 适配器模式

    #### 模板方法模式

    定义:基于继承的设计模式,在父类中定义需要实现的方法,并定义好方法的执行逻辑,子类只需实现对应方法即可

    简介:模板方法模式是一种只需通过继承就可以实现的简单模式。这种模式在前端框架中十分常见,vue、react的组件定义都用到了该模式。大家思考下为什么我们在vue组件中定义的生命周期函数会按照给定的顺序执行呢?通过下面的简单示例来了解下。

    例:

    ```

    var Vue = function (config) { // 父类

        this.config = config

    }

    // 定义需要实现的方法

    Vue.prototype.created = function () {}

    Vue.prototype.mounted = function () {}

    Vue.prototype.destoryed = function () {}

    // 定义执行逻辑

    Vue.prototype.init = function () {

        this.created()

        this.mounted()

        this.destoryed()

    }

    var Button = function (config) {

        Vue.call(this, config)

    }

    Button.prototype = new Vue()

    Button.prototype.created = function () {

        console.log('button created')

    }

    Button.prototype.mounted = function () {

        console.log('button mounted')

    }

    Button.prototype.destoryed = function () {

        console.log('button destoryed')

    }

    var button = new Button()

    ```

    #### 享元模式

    定义:将对象属性划分为内、外两种属性,共享内部状态节约内存

    简介:享元模式是一种用于性能优化的模式,避免创建大量类似的对象,占用大量内存。

    例:

    ```

    var Hero = function (name) {

        this.name = name // 内部状态

    }

    Hero.prototype.show = function () {

        console.log('我', this.name, '的新皮肤-', this.skin, '可真好看')

    }

    var GayLun = new Hero('盖伦')

    var skins = ['乞丐装', '官人装', '皇帝装']

    for (var index = 0; index < skins.length; index++) {

        GayLun.skin = skins[index]; // 外部状态

        GayLun.show()

    }

    ```

    #### 责任链模式

    定义:将一系列处理方法连成链条,请求在这个链条中传递,直到遇到一个可以处理它的方法。

    简介:如果大家接触过node开发,可能会比较好理解这个模式。node开发中我们会定义许多中间件依次挂载到node实例上。当服务器收到请求时请求回依次通过这些中间件方法,这些方法收到请求对象时会判断并处理该请求,然后传给下一个方法。

    ```

    var ming = function(next, subject){

        console.log(next);

        if ( subject === '1+1' ){

            console.log( '这题我会是2' )

        } else {

            next(subject) //我不知道下一个节点是谁,反正把请求往后面传递

        }

    };

    var zhang = function(next, subject){

        if ( subject === '1-1' ){

            console.log( '这题我会是0' )

        } else {

            next(subject) //我不知道下一个节点是谁,反正把请求往后面传递

        }

    };

    var wang = function(next, subject){

        if ( subject === '1*1' ){

            console.log( '这题我会是1' )

        } else {

            next(subject) //我不知道下一个节点是谁,反正把请求往后面传递

        }

    };

    var Chain = function() {

        this.line = []

        this.index = 0

    }

    Chain.prototype.add = function(fn) {

        this.line.push(fn)

    }

    Chain.prototype.exec = function() {

        this.line[this.index](this.next.bind(this), ...arguments)

    }

    Chain.prototype.next = function() {

        var fn = this.line[++ this.index]

        if(fn) {

            fn.apply(this, [this.next.bind(this), ...arguments])

        } else {

            console.log('end')

        }

    }

    var studentChain = new Chain()

    studentChain.add(ming)

    studentChain.add(zhang)

    studentChain.add(wang)

    studentChain.exec('1+1')

    ```

    #### 中介者模式

    定义:解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的 相关对象都通过中介者对象来通信。

    简介:中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。中介者

    模式使网状的多对多关系变成了相对简单的一对多关系。中介者也被称为调停者,我们想象一下机场的指挥塔,如果没有指挥塔的存在,每一架飞机 要和方圆 100 公里内的所有飞机通信,才能确定航线以及飞行状况,后果是不可想象的。现实中 的情况是,每架飞机都只需要和指挥塔通信。指挥塔作为调停者,知道每一架飞机的飞行状况, 所以它可以安排所有飞机的起降时间,及时做出航线调整。

    ```

    function Airplane(num) {

        this.num = num

        this.state = 'out'

    }

    function Airport(maxCount) {

        this.planes = []

        this.maxCount = maxCount

    }

    Airport.prototype.enter = function (plane) {

        var count = this.planes.filter(e => e.state !== 'out').length

        if(count < this.maxCount) {

            var exist = this.planes.find(e => e.num === plane.num)

            if(exist) {

                exist.state = 'in'

            } else {

                plane.state = 'in'

                this.planes.push(plane)

            }

            console.log('运行降落');

        } else {

            console.log('满了你飞别处去吧');

        }

    }

    Airport.prototype.leave = function (plane) {

        var exist = this.planes.find(e => e.num === plane.num)

        exist.state = 'out'

    }

    var plane1 = new Airplane('1-1')

    var plane2 = new Airplane('1-2')

    var plane3 = new Airplane('1-3')

    var airport = new Airport(2)

    airport.enter(plane1)

    airport.enter(plane2)

    airport.enter(plane3)

    airport.leave(plane2)

    airport.enter(plane3)

    ```

    #### 装饰者模式

    定义:给对象动态地增加职责的方式称为装 饰者(decorator)模式

    简介:装饰者模式能够在不改 变对象自身的基础上,在程序运行期间给对象 动态地添加职责。跟继承相比,装饰者是一种 更轻便灵活的做法(超类和子类之间存在强耦合性,当超类改变时,子类也会随之 改变)

    例:在飞机大战游戏中,我们可以吃到一些额外的的武器包来强化我们的小飞机

    ```

    var Plane = function () {

        this.plane = plane;

    }

    Plane.prototype.fire = function () {

        console.log('发射子弹');

    }

    var MissileDecorator = function (plane) {

        this.plane = plane;

    }

    MissileDecorator.prototype.fire = function () {

        this.plane.fire();

        console.log('两侧发射导弹');

    }

    var plane = new Plane();

    plane = new MissileDecorator(plane);

    plane.fire();

    ```

    #### 状态模式

    定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

    简介:状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变。

    相对于策略模式来说状态模式中,状态 和状态对应的行为是早已被封装好的,状态之间的切换也早被规定完成,“改变行为”这件事情 发生在状态模式内部。对客户来说,并不需要了解这些细节。这正是状态模式的作用所在。

    例:电灯开关

    ```

    var OffLightState = function (light) {

        this.light = light;

    };

    OffLightState.prototype.buttonWasPressed = function () {

        console.log('开灯'); // offLightState 对应的行为

        this.light.setState(this.light.onLightState); // 切换状态到onLightState

    };

    // WeakLightState:

    var OnLightState = function (light) {

        this.light = light;

    };

    OnLightState.prototype.buttonWasPressed = function () {

        console.log('关灯'); // onLightState 对应的行为

        this.light.setState(this.light.offLightState); // 切换状态到offLightState

    };

    var Light = function () {

        this.offLightState = new OffLightState(this);

        this.onLightState = new OnLightState(this);

        this.currState = this.offLightState;

    };

    Light.prototype.buttonWasPressed = function () {

        this.currState.buttonWasPressed();

    };

    Light.prototype.setState = function (newState) {

        this.currState = newState;

    };

    var light = new Light();

    light.buttonWasPressed() // 开灯

    light.buttonWasPressed() // 关灯

    ```

    #### 适配器模式

    定义:通过包装函数,统一接口定义

    简介:适配器模式主要用来解决两个已有接口之间不匹配的问题,它不考虑这些接口是怎样实 现的,也不考虑它们将来可能会如何演化。适配器模式不需要改变已有的接口,就能够 使它们协同作用。

    例:

    ```

    var googleMap = {

    show: function(){

    console.log( '开始渲染谷歌地图' );

    }

    };

    var baiduMap = {

    display: function(){

    console.log( '开始渲染百度地图' );

    }

    };

    var baiduMapAdapter = {

    show: function(){

    return baiduMap.display();

    }

    };

    renderMap( googleMap ); // 输出:开始渲染谷歌地图

    renderMap( baiduMapAdapter ); // 输出:开始渲染百度地图

    ```

    ## 总结

    相信大家看完这些设计模式后心里不免会有疑惑,有些设计模式之间相似度非常高,但却被拆分为了不同的叫法(如:装饰者模式 和 代理模式,策略模式和状态模式等)。其实我觉得并不用纠结于此,设计模式本身就是为了优化代码性能,提高可读性、拓展性,更满足设计原则。只要能合理运用其中的一些代码技巧写出更好的代码,就行了。希望本系列的文章能对你的学习之路有帮助

    ### 系列链接

    1. [16种JavaScript设计模式(上)](https://www.jianshu.com/p/455c0e34a3c0)

    2. [16种JavaScript设计模式(中)](https://www.jianshu.com/p/993027963b60)

    3. [16种JavaScript设计模式(下)](https://www.jianshu.com/p/0731e71475b2)

    > 本文主要参考了《javascript设计模式与开发实践》一书

    相关文章

      网友评论

        本文标题:16种JavaScript设计模式(下)

        本文链接:https://www.haomeiwen.com/subject/vywvlqtx.html