超级简单的设计模式,看不懂你来打我

简介: 超级简单的设计模式,看不懂你来打我

今天介绍几个经常被提到的设计模式,通俗易懂,包教包会 源码点击这里

单例模式

单例模式的精髓就是不管一个构造函数被实例化多少次,全局只有一个实例

const Singleton = (function () {
    let instance;
    function init () {
        return new Object();
    }
    return function () {
        if (!instance) {
            instance = init();
        }
        return instance;
    }
})()
let mySingleton1 = new Singltron();
let mySingleton2 = new Singltron();
console.log(mySing1 === mySing2) // true

单例模式的本质就是共享同一个作用域链,很明显这是JavaScript闭包机制实现的

观察者模式

观察者模式主要是通过一个目标(Suject)维护一系列的观察者(Observer),当目标发生变化时,通过广播事件,将目标具体的变化通知所有的观察者

观察者模式主要由四个角色组成:目标(Suject)观察者(Observer)具体目标具体观察者

下面的例子中,当data对象的name或者age属性发生变化时,都会对应的观察者会接受到变化


作者:萌萌哒草头将军

链接:https://juejin.cn/post/7222575963565375544

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Observer {
    constructor (code) {
        this.code = code;
    }
    update () {
        console.log('我是:', this.code, '我知道我该更新了')
    }
}
class Suject {
    constructor () {
        this.observerList = [];
    }
    addObserver (observer) {
        this.observerList.push(observer)
    }
    notify () {
        this.observerList.map((observer) => observer.update())
    }
}
// 具体的观察者
const concreteObservver1 = new Observer('concreteObservver1');
const concreteObservver2 = new Observer('concreteObservver2');
const concreteObservver3 = new Observer('concreteObservver3');
const concreteObservver4 = new Observer('concreteObservver4');
// 具体的目标
const concreteSuject1 = new Suject();
const concreteSuject2 = new Suject();
// 具体的对应关系
concreteSuject1.addObserver(concreteObservver1);
concreteSuject1.addObserver(concreteObservver2);
// 具体的对应关系
concreteSuject2.addObserver(concreteObservver3);
concreteSuject2.addObserver(concreteObservver4);
const data = {name: '萌萌哒草头将军', age: 18}
// 当data的name属性变化,对应的观察者concreteObservver1、
// concreteObservver2就会被广播事件通知,从而更新
Object.defineProperty(data, 'name', {
    get: () => this.name,
    set: (newValue) => {
        concreteSuject1.notify();
        this.name = newValue;
    }
})
// 当data的age属性变化,对应的观察者concreteObservver3、
// concreteObservver4就会被广播事件通知,从而更新
Object.defineProperty(data, 'age', {
    get: () => this.age,
    set: (newValue) => {
        concreteSuject2.notify();
        this.age = newValue;
    }
})
data.name = 'mmdctjj'
// 我是: concreteObservver1 我知道我该更新了
// 我是: concreteObservver2 我知道我该更新了
data.age = 18
// 我是: concreteObservver3 我知道我该更新了
// 我是: concreteObservver4 我知道我该更新了

如果Observerupdate方法里是跟新对应的dom,那恭喜你,这和vue的基思路理是一样的了

发布/订阅模式

虽然观察者模式可以轻松实现发布订阅模式的功能,但是观察者模式使得concreteSujectconcreteObservver耦合在了一起,对于复杂的系统,解耦才能算得上是优秀的系统。

发布/订阅者模式(Public/Subscribe),可以很好的解决观察者模式耦合问题,那么它是怎么解耦的呢?

发布/订阅模式提供了主题/事件通道(Topic/event Channer),,订阅者通过Subscribe功能和topic绑定,当发布者发生变化时,将所有的变更通过event广播给所有订阅该topic的订阅者们。这样就将发布者和订阅者完全隔离开了

还是上面的例子,我们用发布/订阅模式实现

class PubSub {
    constructor() {
        this.topics = {}
        this.uuid = 0 // 每个订阅者的唯一标识,可以随时取消订阅
    }
    // 发布器
    publish(topic, value) {
        if (this.topics[topic]) {
            this.topics[topic].map(({ event }) => event(value))
        }
    }
    // 订阅器
    subscribe(topic, event) {
        const uuid = this.uuid++
        this.topics[topic] = this.topics[topic]
            ? [...this.topics[topic], { event, uuid }]
            : [{ event, uuid }]
        return uuid
    }
}
const MyPubSub = (function () {
    let instance;
    function init() {
        return new PubSub();
    }
    return function () {
        if (!instance) {
            instance = init();
        }
        return instance;
    }
})()
const myPubSub = new MyPubSub()
const data = { name: '萌萌哒草头将军', age: 18 }
myPubSub.subscribe('data.name', (value) => console.log(
    '我知道',
    'name发生变化了:',
    value
))
myPubSub.subscribe('data.name', (value) => console.log(
    '我也知道',
    'name发生变化了:',
    value
))
myPubSub.subscribe('data.age', (value) => console.log('我知道', 'age发生变化了:', value))
Object.defineProperty(data, 'name', {
    get: () => this.name,
    set: (newValue) => {
        myPubSub.publish('data.name', newValue)
        this.name = newValue;
    }
})
Object.defineProperty(data, 'age', {
    get: () => this.age,
    set: (newValue) => {
        myPubSub.publish('data.age', newValue)
        this.age = newValue;
    }
})
data.name = 'mmdctjj'
// 我知道 name发生变化了: mmdctjj
// 我也知道 name发生变化了: mmdctjj
data.age = 18
// 我知道 age发生变化了: 18

jauery的实现了标准的发布订阅模式

$.trigger('login', {userName: 'MMDCTJJ', password: '*******'})
$.on('login', (userInfo) => console.log(userInfo))

vue中,可以使用$emit方法和$on

<button @click="$emit('increaseBy', 1)"> Increase by 1 </button>
<MyButton @increase-by="(n) => count += n" />

中介者模式

中介者模式也和观察者类似,中介者模式由中介者订阅者组成 所有的订阅者们不能互相沟通,必须通过中介者同步信息。

const mediator = (function () {
    let topics = [], uuid = 0;
    function subscribe (topic, callback) {
        uuid ++
        topics[topic] = topics[topic]
            ? [...topics[topic], { callback, uuid }]
            : [{ callback, uuid }]
    }
    function publish (topic, value) {
        if (topics[topic]) {
            topics[topic].map(item => item.callback(value))
        }
    }
    return {
        install: function (obj) {
            obj.uuid = uuid
            obj.publish = publish
            obj.subscribe = subscribe
            return obj
        } 
    }
})()
const subscribe1 = mediator.install({})
const subscribe2 = mediator.install({})
const subscribe3 = mediator.install({})
subscribe1.subscribe('data.name', (value) => console.log('我是subscribe1', value))
subscribe2.subscribe('data.name', (value) => console.log('我是subscribe3', value))
const data = { name: '萌萌哒草头将军', age: 18 }
Object.defineProperty(data, 'name', {
    get: () => this.name,
    set: (newValue) => {
        subscribe3.publish('data.name', newValue)
        this.name = newValue;
    }
})
data.name = 'mmdctjj'
// 我是subscribe1 mmdctjj
// 我是subscribe3 mmdctjj

策略模式

策略模式可以在不同的时机,采用不同的策略解决开发中的问题

相信你经常遇到同事这样的代码

// bad
let arr = [1, 2, 3]
arr.map(a => {
    if (a === 1) {
        console.log('11')
    } else if (a === 2) {
        console.log('22')
    } else if (a === 3) {
        console.log('33')
    }
})

这种如果需要优化,可以使用策略模式

class Strategy {
    constructor() {
        this.strategy = {} // JavaScript的策略模式可以通过对象来巧妙实现
    }
    addStrategy(name, callback) {
        this.strategy[name] = callback
    }
    execute(name, args) {
        this.strategy[name]?.(args)
    }
}
// good
let arr = [1, 2, 3]
const strategy = new Strategy()
strategy.addStrategy(1, () => console.log(11))
strategy.addStrategy(2, () => console.log(22))
strategy.addStrategy(3, () => console.log(33))
arr.map(a => strategy.execute(a, 'your args'))

装饰器模式

装饰器模式(Decorater),主要通过扩展已有的类增加新功能,它不会修改底层代码,是一种对象子类继承的替代方案

class YourClass {
    constructor () {
        this.number = 0
    }
    count () {
        this.number ++
        return this.number
    }
}
class Decorater {
    constructor (other) {
        this.number = other.number + 66
    }
    count () {
        this.number = this.number + 100
        return this.number
    }
}
const yourClass = new YourClass()
const decorater = new Decorater(yourClass)
console.log(yourClass.count(), 'yourClass') // 1
console.log(decorater.count(), 'decorater') // 166
console.log(yourClass.count(), 'yourClass') // 2
console.log(decorater.count(), 'decorater') // 266

好了,今天先分享到这里了,欢迎指正

相关文章
|
OLAP 数据库 索引
59.【clickhouse】ClickHouse从入门到放弃-分区表
【clickhouse】ClickHouse从入门到放弃-分区表
59.【clickhouse】ClickHouse从入门到放弃-分区表
|
11月前
|
人工智能 弹性计算 编解码
阿里云GPU云服务器性能、应用场景及收费标准和活动价格参考
GPU云服务器作为阿里云提供的一种高性能计算服务,通过结合GPU与CPU的计算能力,为用户在人工智能、高性能计算等领域提供了强大的支持。其具备覆盖范围广、超强计算能力、网络性能出色等优势,且计费方式灵活多样,能够满足不同用户的需求。目前用户购买阿里云gpu云服务器gn5 规格族(P100-16G)、gn6i 规格族(T4-16G)、gn6v 规格族(V100-16G)有优惠,本文为大家详细介绍阿里云gpu云服务器的相关性能及收费标准与最新活动价格情况,以供参考和选择。
|
Java 程序员 应用服务中间件
程序员必知:Webflux快速入门
程序员必知:Webflux快速入门
474 0
|
Java Linux Maven
Centos7.6安装Maven3.8.3并配置阿里云镜像
Centos7.6安装Maven3.8.3并配置阿里云镜像
1217 0
|
机器学习/深度学习 C语言
C语言必刷题上(保姆式详解)
C语言必刷题上(保姆式详解)
71 0
|
Java 开发者 容器
SpringBoot:详解Bean生命周期和作用域
SpringBoot:详解Bean生命周期和作用域
1027 0
|
机器人 Android开发 数据安全/隐私保护
Android App 导出APK安装包以及制作App图标讲解及实战(图文解释 简单易懂)
Android App 导出APK安装包以及制作App图标讲解及实战(图文解释 简单易懂)
2501 0
|
Java Windows
Jmeter安装配置详细教程
Jmeter安装配置详细教程
477 0
Jmeter安装配置详细教程
|
运维 安全 Linux
【Anolis OS】龙蜥操作系统(Anolis OS) 8.6安装指南
【Anolis OS】龙蜥操作系统(Anolis OS) 8.6安装指南
7370 0
|
C++
直流稳压电源【精华版】
掌握并联型稳压电路的结构与工作过程。 会识别三端集成稳压器的引脚,能连接应用电路。 会制作与调试直流稳压电源电路。 了解家用调光灯电路的工作原理。 了解开关式稳压电源的特点。 二、知识干货总结 (1)稳压电路的作用:保持电源电压或负载变化时,输出的直流电压稳定。 (2)并联型稳压电路: ①稳压二极管 a.结构及材料:稳压二极管是一种面接触型的硅二极管。 b.伏安特性曲线:如图所示: 稳压二极管的知识补充: ①图形符号: ②正常工作时,加反向电压; ③是一种用于稳压、工作于反向击穿状态的二极管; ④当反向电压达到Uz时,反向电流突然剧增,稳压二极管处于击穿状态。 并联型稳压电路如图所示: 组成:
262 0
直流稳压电源【精华版】