JavaScript常用设计模式
设计模式
设计模式是一种在长时间的经验与错误中总结出来可服用的解决方案。
设计模式主要分为3类:
创建型设计模式:专注于处理对象的创建
Constructor构造器模式,Factory工厂模式,Singleton单例模式,builder生成器模式
结构型设计模式:对象间组合,建立对象之间的关系
Decorator装饰者模式,Facade外观模式,Flyweight享元模式,Adapter适配器模式,Proxy代理模式
行为设计模式:简化和改善对象间的通信
Mediator中介者模式,Observer观察者模式
常用的设计模式
1. 观察者模式
一个目标对象维持着一系列依赖于它的对象,将有关状态的任何变更自动通知观察者们。在观察者模式中,观察者需要直接订阅目标对象,观察者与目标对象之间有一定的依赖关系。 有4个重要的概念
- 目标对象(被观察者):维护一组观察患者,提供管理观察者的方法。
- 观察者: 提供一个更新接口,用于收到通知时,进行更新
- 具体目标对象:代表具体的目标对象
- 具体观察者:代表具体的观察者
// 目标对象 class Subject { constructor() { // 观察者列表 this.observers = [] } addObserver(observer) { this.observers.push(observer) } removeObserver() { this.observers.pop() } notify() { this.observers.forEach(observer => { observer.update() }) } } // 观察者 class Observer { constructor() { // 使用时会被具体update方法覆盖 this.update = function () { // .. } } } // 具体目标对象 class currentSubject extends Subject { constructor() { super() } // 其他自定义方法 dosomething() { console.log('currentSubject change') this.notify() } } // 具体观察者 class currentObserver extends Observer { constructor() { super() } // 重写update update() { console.log('change!') } } // 订阅 let curSubject = new currentSubject() let curObserver = new currentObserver() curSubject.addObserver(curObserver) // 触发 curSubject.dosomething() // currentSubject change
2.发布/订阅模式
发布订阅模式可以说是观察这模式的一种变体,一种实现。它使用一个主题/事件通道,介于发布者和订阅者之间,避免了发布者和订阅者之间的依赖关系。
class PubSub { constructor() { // 主题/事件通道 this.topics = {} } publish(topic, args) { if (!this.topics[topic]) { return } let subscribers = this.topics[topic] subscribers.forEach(subscriber => { subscriber.updata(args) }) } subscribe(topic, subscriber ) { if (!this.topics[topic]) { this.topics[topic] = [] } this.topics[topic].push(subscriber ) } } let pubsub = new PubSub() pubsub.subscribe('one', subscriber ) pubsub.publish('one', 'some args')
3. 工厂模式
工厂函数提供一个通用的接口来创建对象,我们可以指定我们希望创建的对象类型,我们通知工厂函数需要什么类型的对象并提供对应的数据,返回对应的实例。
class Car { constructor(options) { this.doors = options.doors || 4; this.state = options.state || "brand new"; this.color = options.color || "silver"; } } class Truck { constructor(options) { this.state = options.state || "used"; this.wheelSize = options.wheelSize || "large"; this.color = options.color || "blue"; } } function vehicleFactory (options) { if (options.type === 'car') { return new Car(options) } else { return new Truck(options) } }
何时使用工厂模式
- 当我们的对象比较复杂的时候。
- 当我们需要根据不同情况创建不同对象实例的时候。
- 当我们需要创建许多相似对象的时候。
缺点
- 使用不当会增加程序的复杂度
4. 抽象工厂模式
抽象工厂模式,将对象的实现细节抽离出来。适用于需要和多种对象一起工作的场景。
class Truck { constructor(options) { this.state = options.state || "used"; this.wheelSize = options.wheelSize || "large"; this.color = options.color || "blue"; } } class Car { constructor(options) { this.doors = options.doors || 4; this.state = options.state || "brand new"; this.color = options.color || "silver"; } } class AbstractFactory { constructor() { this.types = {} } registerFactory(type, factory) { this.types[type] = factory } getInstance(type, args) { let factory = this.types[type] if (factory) { return new factory(args) } } } let abstractFactory = new AbortController() abstractFactory.registerFactory('car', Car) abstractFactory.registerFactory('truck', Truck) abstractFactory.getInstance('car', options) abstractFactory.getInstance('truck', options)
5. 单例模式
单例模式限制一个类只有一个实例化对象。
class Obj(data) { // .... } // 利用闭包实现单例模式,确保obj类只有一个实例 function singleton (data) { var instance; return function () { if (!instance) { instance = new Obj(data) } return instance } }
6. 中介者模式
中介者模式就是提供一个中心点给系统不同组件之间进行通信,降低系统组件之间的耦合程度。
// 实现与发布/订阅模式类似
观察者模式和发布订阅模式专注于维护目标对象和观察者之间的关系,当主题对象发送变化时,通知所有对改主题感兴趣的观察者。而中介者模式的话,专注于限制对象的通信必须通过中介者来通信。两者都提倡松耦合。
7. 装饰者模式
装饰者模式,通过一个装饰类对现有动态添加行为,以及对原有行为进行装饰。
// o为已有对象 var M20 = function(o){ // 这里定义一个装饰类 var str = '20多岁的时候,'; // o是传入的对象,调用传入对象的方法,加以装饰 this.eat = function(){ return str + o.eat()+",肥得很!"; }; this.drink = function(){ return str + o.drink()+",就是个水桶!"; }; this.coding = function(){ return str + o.coding()+",代码又写得撇!"; }; } alert(new M20(david).eat()); // 20多岁的时候,大卫是个大胖子,一天只晓得吃,肥得很! alert(new M20(david).drink()); // 20多岁的时候,大卫除了吃就是喝,就是个水桶! alert(new M20(david).coding()); // 20多岁的时候,写代码吧,大卫,代码又写得撇!
8. 适配器模式
使用一个新的接口对现有的接口进行包装,处理数据与接口的不匹配。
function api (x1, x2, x3) { console.log(x1 + x2 + x3); // 用console.log来模拟接口的相关操作 } var data = { a: '我', b: '很', c: '帅' } function adapterApi (o) { // 通过适配器函数来调用目的api api(o.a, o.b, o.c); } adapterApi(data); // 我很帅
原文发布时间为:2018年07月02日
原文作者:掘金
本文来源:掘金 如需转载请联系原作者
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JavaScript 内存机制(前端同学进阶必备)
简介 每种编程语言都有它的内存管理机制,比如简单的C有低级的内存管理基元,像malloc(),free()。同样我们在学习JavaScript的时候,很有必要了解JavaScript的内存管理机制。 JavaScript的内存管理机制是:内存基元在变量(对象,字符串等等)创建时分配,然后在他们不再被使用时“自动”释放。后者被称为垃圾回收。这个“自动”是混淆并给JavaScript(和其他高级语言)开发者一个错觉:他们可以不用考虑内存管理。 对于前端开发来说,内存空间并不是一个经常被提及的概念,很容易被大家忽视。当然也包括我自己。在很长一段时间里认为内存空间的概念在JS的学习中并不是那么重要。可是后我当我回过头来重新整理JS基础时,发现由于对它们的模糊认知,导致了很多东西我都理解得并不明白。比如最基本的引用数据类型和引用传递到底是怎么回事儿?比如浅复制与深复制有什么不同?还有闭包,原型等等。 但其实在使用JavaScript进行开发的过程中,了解JavaScript内存机制有助于开发人员能够清晰的认识到自己写的代码在执行的过程中发生过什么,也能够提高项目的代码质量。 内存模型 JS内存空...
- 下一篇
C++中一个名字查找的小知识
最近看C++标准中的3.4 name lookup章节,碰巧的是stackoverflow也有人提问,他们对这个问题很疑惑,回答的也并不好。https://stackoverflow.com/questions/25672745/friend-declarations-is-this-a-bug-in-clang 其中C++标准中$3.4.1章节有一个例子: typedef int f; namespace N { struct A { friend void f(A &); operator int(); void g(A a) { int i = f(a); // f is the typedef, not the f
相关文章
文章评论
共有0条评论来说两句吧...