23种设计模式
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象
工厂模式
-
简单工厂模式
在不动之前的逻辑的基础上,继承和扩展新的功能,这样我们就可以提高效率,之前写好的功能可以复用,站在巨人的肩膀上,不断扩展。但是缺点是,直接new实例,耦合依赖具体的实现
-
工厂方法模式
工厂方法模式就是我们可以增加不同的水果,我们不用关心如何实现,新增同一个水果类,拿来就用,还有一个好处就是,比如apple有改动新增新的功能,但是引用的地方很多,我们就只需要新增一个appleFactory,修改不影响老代码。
class Plant{ constructor(name) { this.name=name; } grow() { console.log('growing~~~~~~'); } } // 新增Factory class Factory { create() { } } class Apple extends Plant{ constructor(name, color) { super(name); this.color = color } } class Orange extends Plant{ constructor(name, color) { super(name); this.color = color } } // 子类继承父类 并实现create 方法 class AppleFactory extends Factory{ static create() { return new Apple('苹果','红色'); } } class OrangeFactory extends Factory{ static create() { return new Orange('桔子', '橙色'); } } // 通过配置文件来解耦合 const settings={ 'apple': AppleFactory, 'orange':OrangeFactory } let apple=new settings['apple']().create(); let orange=new settings['orange']().create();类Factory
- 工厂一般是接口,规定子类必须实现的方法
-
依赖抽象,而不依赖实现
- 接口只有方法定义,没有具体的实现,如果一个类要实现该接口,就必须实现该接口中的所有方法
-
抽象工厂模式
抽象工厂模式
工厂模式通常会分成3个角色:
- 工厂角色-负责实现创建所有实例的内部逻辑.
- 抽象产品角色-是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
- 具体产品角色-是创建目标,所有创建的对象都充当这个角色的某个具体类的实例
策略模式
策略模式,就是定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换
至少分成两部分:
- 策略类(可变),策略类封装了具体的算法,并负责具体的计算过程
- 环境类(不变),接受客户的请求,随后将请求委托给某一个策略类
# 代理模式
代理模式:为对象提供一个代用品或占位符,以便控制对它的访问
代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要时,提供一个替身对象来控制这个对象的访问,客户实际上访问的是替身对象。
例如:实现图片懒加载的功能,先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面,
按照功能来划分,JavaScript分为缓存代理和虚拟代理
缓存代理:用于计算量大的,缓存计算的结果,下次计算的时候,只需要对比传递的参数,如果参数相同直接返回缓存的结果
虚拟代理:例如图片的loading 先用一张loading图站位
使用代理模式代理对象的访问的方式,一般又称为拦截器,比如我们项目中经常使用axios的实例来进行HTTP的请求,使用拦截器interceptor可以提供对请求数据服务器返回的数据进行一些预处理
# 中介者模式
中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可
通过中介者模式可以解除对象与对象之间的紧耦合关系
# 装饰者模式
装饰者模式的定义:在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法
通常运用在原有方法维持不变,在原有方法上再挂载其他方法来满足现有需
1. 发布-订阅,观察者模式的区别
生活例子:
- 观察者模式:某公司给自己员工发月饼发粽子,是由公司的行政部门发送的,这件事不适合交给第三方,原因是“公司”和“员工”是一个整体
- 发布- 订阅模式:某公司要给其他人发各种快递,因为“公司”和其他人是独立的,其唯一的桥梁是“快递”,所以这件事适合交给第三方快递公司解决
两者区别如下:
- 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅者模式中,发布者和订阅者不知道对方的存在。他们只有通过消息代理进行通信。
- 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
- 观察者模式大多数时候使同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数是异步的(使用消息队列)