设计模式
通常在我们解决问题的时候,很多时候不是只有一种方式,我们通常有多种方式来解决;但是肯定会有一种通用且高效的解决方案,这种解决方案在软件开发中我们称它为设计模式;设计模式是解决软件开发某些特定问题而提出的一些解决方案,也可以理解成解决问题的一些思路,设计模式并不是一种固定的公式,而是一种思想,是一种解决问题的思路;恰当的使用设计模式,可以实现代码的复用和提高可维护性。
设计模式分类
在程序设计中我们通常认为是有23种设计模式,根据目的、用途的不同,分为创建性模式、结构性模式、行为性模式。
1、创建型设计模式
创建型设计模式主要是用于处理对象创建的模式,对类的实例化过程 进行了抽象,将对象的创建和对象的使用分离
- 构造器模式(Constructor)
- 工厂模式(Factory)
- 抽象工厂模式 (Abstract)
- 原型模式 (Prototype)
- 单例模式 (Singleton)
- 建造者模式(Builder)
2、结构型设计模式
主要用于处理类和对象的组合
- 适配器模式
- 桥接模式
- 组合模式
- 装饰者模式
- 外观模式
- 享元模式
- 代理模式
3、行为型
主要用于描述类或对象的交互以及职责分配
- 职责链模式
- 命令模式
- 解释器模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式(又称发布/订阅模式)
- 状态模式
- 策略模式
- 访问者模式
- 模板方法模式
JavaScript 设计模式分类概览表
下面简单介绍一下前端常用的5种设计模式:
- 工厂模式
是用来创建对象的一种最常用的设计模式。我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂
function Person(opts) { var obj = new Object(); obj.name = opts.name; obj.age = opts.age; obj.getInfo = function () { return '名称:' + obj.name + ', 年龄:' + obj.color; } return obj; } var person = Person({ name: '张三', age: '14' }); person.getInfo();
- 构造函数模式
function Person(name, age) { this.name = name; this.age = age; this.getName = function () { return this.name; }, this.getAge = function () { return this.age; } } // 实例一个对象 var person = new Person('张三', '14'); console.log(person.getName()); console.log(person.getAge());
工厂模式和构造函数模式看似有点像,其实主要的区别在于工厂模式将对象的创建放在了内部,用通俗化的语言来说,Person就相当于是一个工厂,你告诉工厂你想要什么东西,然后工厂就会去生产你想要的东西
工厂模式的详细介绍,点https://www.jianshu.com/p/11918dd0f694
- 单例模式
单例模式之所以这么叫,是因为它限制一个类只能有一个实例化对象。经典的实现方式是,创建一个类,这个类包含一个方法(静态方法,一般是getInstance命名),这个方法在没有对象存在的情况下,会创建一个新的实例对象。如果对象存在,这个方法只是返回这个对象的引用
-
特点:
- 单例类只有一个对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点
export class ModelLocator { public static _instance: ModelLocator = null; _name: any = 'test'; constructor() { if (ModelLocator._instance) { throw new Error("Error: Instantiation failed: Use ModelLocator.getInstance() instead of new."); } ModelLocator._instance = this; } public static getInstance(): ModelLocator { if (ModelLocator._instance == null) { console.log("ModelLocator create start"); ModelLocator._instance = new ModelLocator(); } return ModelLocator._instance; } get name() { return this._name; } set name(value) { this._name = value; } } //获取实例的内容 //let name = ModelLocator.getInstance().name;
- 观察者模式
一个被称作被观察者的对象,维护一组被称为观察者的对象,这些对象依赖于被观察者,被观察者自动将自身的状态的任何变化通知给它们。
简单的说就是用于将变化通知给多个类的方式,可以保证类之间的一致性,实际上就是广播式的通知,像vue的双向数据绑定、消息通讯websocket等都是观察者模式。
举一个例子:
假如你去苹果专卖店买最新款的iphone11,因为iphone11刚出来不久,正处旺季,供货不足;当你去专卖店的时候,店员告诉你暂时没货了,但是你可以留下你的联系方式,如果货到了,会第一时间通知;当然你肯定不会每天都去专卖店问iphone11到货没有,也不会天天给专卖店打电话,因为你有你自己的工作和生活,不可能有那么多闲暇时间;所以此时,店员让你留下联系方式,到货了第一时间通知你,不会给你带来麻烦,而你只需要等着专卖店的电话即可;而这种方法就是一种典型的观察者模式。
- 策略模式
这个模式可能大家都不常听到,但它却是很常用的模式,也许你在平时不知不觉中就已经使用了这个模式,只有你有封装,那么就大概率会使用。
所谓的策略模式就是指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
简单的说 就是将算法封装到类中,将选择和实现分离开来。
//没有使用策略模式 function calcSalary(original, grade) { var final; if (grade == "A") { final = original * 3 } else if (grade == "B") { final = original * 2 } else if (grade == "C") { final = original * 1.5 } return final } console.log(calcSalary(2000, 'A')) // 6000
//使用策略模式 var strategies = { //一组策略 "A": function (original) { return original * 3 }, "B": function (original) { return original * 2 }, "C": function (original) { return original * 1.5 } } function calcSalary(original, grade) { //调用环境 return strategies[grade](original) } console.log(calcSalary(2000, 'A')) // 6000
w3cschool有很详细的解释和介绍以及例子,但是可能会稍微抽象了点:https://www.w3cschool.cn/zobyhd/