js设计模式-工厂模式 单例模式 观察者模式 发布订阅模式 原型模式 代理模式 迭代器模式

1 工厂模式

// 工厂模式: 调用函数返回对象

function factory(name, age){
    return {
        name: name,
        age: age
    }
}

const person1 = factory('Tom', 18);
// 类似的库使用工厂函数的有: jQuery, React.createElement,axios.create,vue.createApp等

2 单例模式

// 单例模式:单例方法返回唯一实例 单例模式的核心是确保只有一个实例,并提供全局访问
// 单例模式实现

class SingleTon {
    static #instance = null;

    static getInstance(){
        if(!this.#instance){
            this.#instance = new SingleTon();
        }
        return this.#instance;
    }
}
// 这是单例模式的方法
const singleTon1 = SingleTon.getInstance();
const singleTon2 = SingleTon.getInstance();
console.log(singleTon1 === singleTon2); // true
// 类似的库使用单例模式的有: vue.use vant中的notify等

3 观察者模式

// 观察者模式:一个对象可能有一个或多个观察者,当对象状态发生变化时,会通知所有观察者(执行对应的回调)
// 最典型的例子是DOM事件 如下就是一个简单的观察者模式
const button = document.getElementById('button');
button.addEventListener('click', function(){
    console.log('click');
})
// 可以有多个事件监听器(观察者)
button.addEventListener('click', function(){
    console.log('click2');
})

4 发布订阅模式

// 发布订阅模式:发布者和订阅者之间没有直接联系,通过第三方来实现调度(事件总线)
// 一般来说有四种行为 $on注册事件 $off清除事件 $emit触发时间 $once仅触发一次
// 现在简单的实现一个发布订阅模式
class MygoEventBus{
    #handlers = {}

    $on(event, callback){
        if(!this.#handlers[event]){
            this.#handlers[event] = []
        }
        this.#handlers[event].push(callback)
    }

    $emit(event, ...args){
        this.#handlers[event] ||  (this.#handlers[event] = [])
        this.#handlers[event].forEach(callback => {
            callback(...args)
        })
    }

    $off(event){
        this.#handlers[event] = undefined
    }

    $once(event, callback){
        this.$on(event, (...args) => {
            callback(...args)
            this.$off(event)
        })
    }
}


// 测试代码
const bus = new MygoEventBus();
bus.$on('click', function(){
    console.log('click');
})
bus.$on('click', function(){
    console.log('click2');
})
bus.$emit('click');
bus.$emit('click');
bus.$off('click');
bus.$emit('click');
bus.$once('click', function(){
    console.log('click3');
})
bus.$emit('click');
bus.$emit('click');
// 输出结果为 click click2 click click2 click3

5 原型模式

// 原型模式:类似于使用object.create()方法创建对象
// 通过原型模式创建对象
const person = {
    name: 'Tom',
    age: 18
}

const person2 = Object.create(person);
// 再Vue中数组和对象的响应式原理就是通过原型模式实现的

6 代理模式

// 代理模式:代理模式是为一个对象提供一个代用品或占位符,以便控制对它的访问
// 下面举例一个应用场景(类似于DNS查找)就是数据缓存中间件 代码如下:
class AreaData{
    cache = {}

    getAreaCode(code){
        if(!this.cache[code]){
            // 模拟请求数据
            console.log('请求数据')
            this.cache[code] = 'area' + code
        }
        return this.cache[code]
    }
}

const areaData = new AreaData();
console.log(areaData.getAreaCode(1));
// 第二次请求数据时,直接返回缓存数据
console.log(areaData.getAreaCode(1));
console.log(areaData.getAreaCode(2));

7 迭代器模式

// 迭代器模式:只要一个对象实现了迭代器协议和next方法,就可以被for...of循环遍历
// 实现迭代器可以使用generator或者手动实现
// [Symbol.iterator]要求返回一个迭代器对象,迭代器对象要求有next方法,next方法返回一个对象,对象有value和done两个属性
const obj = {
    [Symbol.iterator]: () =>{
        function* gen(){
            yield 1;
            yield 2;
            yield 3;
        }
        return gen();
    }
}

for(let item of obj){
    console.log(item); // 1 2 3
}

// 手动实现迭代器
const obj2 = {
    data: [1, 2, 3],
    [Symbol.iterator]: function(){
        let index = 0;
        let that = this;
        return {
            next(){
                return {
                    value: that.data[index],
                    done: index++ === that.data.length
                }
            }
        }
    }
}

for(let item of obj2){
    console.log(item); // 1 2 3
}

// 迭代器模式模仿python中的range
function* range(end){
    for(let i = 0; i < end; i ++){
        yield i;
    }
}

for(let item of range(10)){
    console.log(item); // 0 1 2 3 4 5 6 7 8 9
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值