设计模式的概念

语言: CN / TW / HK

这是我参与「第四届青训营」笔记创作活动的的第8天

设计模式的概念

设计模式就是前辈们代码设计的一个总结,也就是写代码的最佳实践,让代码有更好的可复用性、可读性、可维护性,设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。目前为止共有23种设计模式,但是有些设计模式不太常用。

7大设计原则

1.单一职责原则 SRP

我们设计的类尽量负责一项功能,如A类只负责功能A,B类只负责功能B,不要让A类既负责功能A,又负责功能B,这样会导致代码混乱,容易产生bug。

2.开放-封闭原则 OCP

是编程汇总最基础,最重要的设计原则,核心为对扩展开发,对修改关闭,简单来说,通过扩展软件的行为来实现变化,而不是通过修改来实现,尽量不修改代码,而是扩展代码。

3.里氏替换原则 LSP

程序中的子类应该可以替换父类出现的任何地方并保持预期不变。所以子类尽量不要改变父类方法的预期行为。

4.接口隔离原则 ISP

类不应该依赖他不需要的接口,接口尽量小颗粒划分。当类 A 只需要接口 B 中的部分方法时,因为实现接口需要实现其所有的方法,于是就造成了类 A 多出了部分不需要的代码。这时应该将 B 接口拆分,将类A需要和不需要的方法隔离开来。

5.依赖倒置原则 DIP

抽象不应该依赖细节,细节应该依赖于抽象。核心是面向接口编程,我们应该依赖于抽象接口,而不是具体的接口实现类或具体的对象。相对于细节的多变性,抽象的东西要稳定的多,以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。

6.最少知识原则(迪米特原则)LOD

一个类或对象应该对其它对象保持最少的了解。只与直接的朋友(耦合)通信。

7.组合/聚合复用原则 CRP

尽可能通过组合已有对象(借用他们的能力)来实现新的功能,而不是使用继承来获取这些能力。就是能用组合实现少用继承。

前端常用设计模式之一--发布订阅模式

在很多的库里都能见到这个设计模式的应用,在nodejs里对事件的监听基本都是用EventEmitter实现的,在这里实现一个简单的EventEmitter。

代码如下:

``` class EventEmitter { constructor() { this._events = {} }

on(eventName, callback) { if (!this._events) { this._events = {} } if (this._events[eventName]) { this._events[eventName].push(callback) } else { this._events[eventName] = [callback] } } emit(eventName, ...args) { this._events[eventName].forEach((fn) => { fn(...args) }) } off(eventName, callback) { if (this._events && this._events[eventName]) { this._events[eventName] = this._events[eventName].filter( (fn) => fn !== callback && fn.a !== callback ) } }

once(eventName, callback) { const one = () => { callback() this.off(eventName, one) } one.a = callback this.on(eventName, one) } } 复制代码 ```

测试代码如下:

``` class Child extends EventEmitter { constructor() { super() } }

const child = new Child()

const happy = () => { console.log('i love you') }

const unhappy = () => { console.log('你个老六') } child.on('给你糖', happy) child.on('把你糖抢回来', unhappy)

const fn = () => { console.log('逛街') }

child.once('干什么', fn)

child.emit('给你糖')

console.log('________')

child.emit('把你糖抢回来')

console.log('________') setTimeout(() => { child.off('干什么', fn) child.emit('干什么') }, 1000) 复制代码 ```

测试结果如下图:

image.png

「其他文章」