javascript设计模式及应用场景

栏目: JavaScript · 发布时间: 6年前

内容简介:这里花几分钟时间来讲解几个设计模式以及它们的应用场景。可以帮助你在平时开发时把设计模式用起来废话不多说,直接上demo目前浏览器不支持装饰器模式,如果想要让这段代码跑起来的话,需要依赖babel的一个插件:babel-plugin-transform-decorators-legacy

这里花几分钟时间来讲解几个 设计模式 以及它们的应用场景。可以帮助你在平时开发时把设计模式用起来

  • 装饰器模式
  • 迭代器模式
  • 发布订阅模式
  • 工厂模式
  • 单例模式
  • 代理模式
  • 外观模式

废话不多说,直接上demo

装饰器模式

装饰器DEMO

<!--index.js-->
function decoratorHoc(target){
    target.customerName = 'xuqiang';
}

@decoratorHoc
class Person{}

console.log(Person.customerName);
复制代码

装饰器疑问 ️

  • decoratorHoc是个函数,为何支持@decoratorHoc?不要把这个当作理所当然。可以试下把代码拷入vscode,然后code runner,发现报了这段错
javascript设计模式及应用场景

目前浏览器不支持装饰器模式,如果想要让这段代码跑起来的话,需要依赖babel的一个插件:babel-plugin-transform-decorators-legacy

那么下面三步来把babel环境搞一下

  • 安装全局babel
<!--在当前index.js目录下-->
yarn add babel-cli -g

yarn add babel-plugin-transform-decorators-legacy
复制代码
  • 配置.babelrc
<!--在当前index.js目录下新建.babelrc文件,内容如下-->
{
    plugins: ['transform-decorators-legacy']
}
复制代码
  • 编译index.js
<!--在当前index.js目录下-->
babel index.js --out-file compiled.js
复制代码

这里把index.js编译为了compiled.js。然后code runner compiled.js,发现日志输出了"xuqiang"

javascript设计模式及应用场景

至此你就实现了装饰器decoratorHoc

装饰器模式应用场景

装饰器模式可以说是非常方便地扩展了一个对象。那么平时开发中是不是有几类代码跟装饰器模式很相似

  • react的高阶组件
  • dva的@connect

这里就举两个例子,更多场景需要你自己去发现了

迭代器模式

迭代一个对象,就可以称为是迭代器,下面从es6的迭代器来讲解下

for-of遍历json

这是一个es6的自定义迭代器DEMO,讲解如何写一个迭代器来遍历普通对象,因为遍历数组内置已经支持了

let obj = {
    name: 'xuqiang',
    age: 20,
    [Symbol.iterator]: () => {
        let props = Object.keys(obj), i = props.length;
        return {
            next(){
                if(i > 0){
                    i = i - 1;
                    return {
                        value: obj[props[props.length - i - 1]],
                        done: false
                    };
                }else{
                    return {
                        value: '',
                        done: true
                    };
                }
            }
        };
    }
}

for(let prop of obj){
    console.log(prop);
}
复制代码

code runner发现可以正确遍历一个Object了

javascript设计模式及应用场景

发布订阅模式

发布订阅的场景

用一个老生常谈的场景先来解释下发布订阅,那就是学生时代的订牛奶,先来整理下需求

  • 有一个工厂,有一个let products = {},有一种属性叫做牛奶。此属性对应一个数组,数组存储每个订奶牛人的数据。
  • 工厂有一个定时器,每天早上8点开始遍历products,进行牛奶派发
  • 有很多消费者,向工厂订牛奶

需求整理清楚了,下面用个DEMO来实现下

// 发布订阅模式
// 发布订阅模式

class Puber{
    constructor(name){
        this.name = name;
        this.products = {};
        this.startInterval();
    }

    startInterval(){
        setInterval(() => {
            for(let prop in this.products){
                if(this.products.hasOwnProperty(prop)){
                    this.emit(prop);
                }
            }
        }, 3000);
    }

    sub(evt, cb){
        if(!this.products[evt]){
            this.products[evt] = [];
        }
        this.products[evt].push(cb);
    }

    emit(evt){
        if(this.products[evt]){
            let cbs = this.products[evt];
            for(let cb of cbs){
                cb && cb();
            }
        }
    }
}

class Suber{
    constructor(name){
        this.name = name;
        this.puber = new Puber('徐强');
    }

    getPuber(){
        console.log(`我是${this.name},我的牛奶配送员是${this.puber.name}`);
    }

    sub(evt, cb){
        this.puber.sub(evt, cb);
    }
}

let customer1 = new Suber('刘思琪');
customer1.getPuber();
customer1.sub('牛奶', () => {
    console.log(`现在时间是${+new Date},牛奶送至未来科技城,收件人:刘思琪`);
});

let customer2 = new Suber('徐大佬');
customer2.getPuber();
customer2.sub('牛奶', () => {
    console.log(`现在时间是${+new Date},牛奶送至空港新城,收件人:徐大佬`);
});
复制代码
javascript设计模式及应用场景

发现刘思琪和徐大佬,已经成功订了牛奶,并且每天早上10点钟开始派发牛奶了。当然了,这里没有写取消订牛奶的操作,大家可以自己接着写

工厂模式

class jQuery{
    constructor(name){
        this.name = name;
    }
}

function $(name){
    return new jQuery(name);
}

let obj1 = $('xuqiang');
let obj2 = $('liusiqi');
console.log(obj1);
console.log(obj2);
复制代码

工厂模式总结

这里举例也是用的jquery,可以发现jquery的$函数就是用了工厂模式,那么工厂模式有哪些好处呢?

  • 不需要自己调用new jQuery。直接用$很方便
  • 类似React.createElement,屏蔽了开发者直接使用new VNode,符合开放封闭原则,VNode的实现对开发者不可见

单例模式

光是单例模式的话比较简单,感觉没什么亮点,所以这里结合装饰器模式来写一个单例模式

写一个装饰器模式+单例模式的骚操作

function getInstanceHoc(target){
    target.getInstance = (() => {
        let instance;
        return () => {
            if(!instance){
                instance = new Function(`return new ${target}()`)();
            }
            return instance;
        }
    })();
}

@getInstanceHoc
class Person{
    eat(){
        console.log('i am eating');
    }
}

let obj = Person.getInstance();
console.log(obj);
obj.eat();

let obj1 = Person.getInstance();
console.log(obj === obj1);
复制代码

code runner之后发现,obj和obj1都可以eat了,然后比较obj===obj1,发现是true,说明单例模式已经成功了

javascript设计模式及应用场景

代理模式

用es6的Proxy来讲一下代理

class Vue{
    constructor(data){
        let _data =  data;

        return new Proxy(this, {
            get(target, key){
                return _data[key];
            },
            set(target, key, val){
                _data[key] = val;
            }
        });
    }
}

let obj = new Vue({
    name: '徐强',
    age: 20
});
console.log(obj.name);
obj.name = '刘思琪';
console.log(obj.name);
复制代码
javascript设计模式及应用场景

外观模式

外观模式在jquery中很常见。在我们平时开发中感觉也很好用

function winAlert(title, message, buttons, cb){
    if(cb === undefined){
        cb = buttons;
        buttons = null;
    }

    console.log(title);
    console.log(message);
    console.log(buttons);
    console.log(cb);
}

winAlert('提示', '操作完成', ['确认', '取消'], () => {});

winAlert('提示', '操作完成', () => {});
复制代码

运行结果:

javascript设计模式及应用场景

这让我想起目前业务中后端所有接口都是app/htmlGateway.do,只是version,rd等参数区别,从某种角度来说这是符合外观模式的。封闭后端api的内部实现,开放htmlGetway给前端调用

但是目前这种方式有个问题是,对于yapi,rap2等mock平台不太友好。因为api路径都是一致的,会不太好mock,也可能是因为我没有发现解决方案吧,所以觉得不太好mock

ok 这几种设计模式的demo都已经讲完了。有问题可以一起谈论。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Dive Into Python 3

Dive Into Python 3

Mark Pilgrim / Apress / 2009-11-6 / USD 44.99

Mark Pilgrim's Dive Into Python 3 is a hands-on guide to Python 3 (the latest version of the Python language) and its differences from Python 2. As in the original book, Dive Into Python, each chapter......一起来看看 《Dive Into Python 3》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具