前端设计模式

100 阅读5分钟

23种设计模式

总体来说设计模式分为三大类:

创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

单例模式

保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象

工厂模式

  • 简单工厂模式

    在不动之前的逻辑的基础上,继承和扩展新的功能,这样我们就可以提高效率,之前写好的功能可以复用,站在巨人的肩膀上,不断扩展。但是缺点是,直接new实例,耦合依赖具体的实现

  • 工厂方法模式

    img

    工厂方法模式就是我们可以增加不同的水果,我们不用关心如何实现,新增同一个水果类,拿来就用,还有一个好处就是,比如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就会去调用观察者的方法。而发布-订阅模式大多数是异步的(使用消息队列)