JavaScript设计模式 – 设计原则
说明
可以说每种设计模式都是为了让代码迎合其中一个或者多个原则而出现的,他们本身已经融入到了设计模式之中
- 单一职责原则(SRP)
- 最少知识原则(LKP)(迪米特法则)
- 开放-封闭原则(OCP)
- 里氏转换原则
- 依赖倒转原则
1. 单一职责原则(SRP)
指的是,对一个类而言(包括对象和函数),应该仅有一个引起它变化的原因,如果一个对象承担了多项职责,就意味着这个对象将变得巨大,引起它变化的原因可能会有多个,面向对象设计鼓励将行为分布到细粒度的对象之中,如果一个对象承担的职责过多,等于把这些职责耦合到了一起,这种耦合会导致脆弱和第内聚的设计,当变化发生时,设计可能会遭到以外的破坏。
何时去分离职责
SRP 原则是所有原则当中最简单也是最难正确运用的原则之一,要明确的是,并不是所有的职责都应该一一分离。
- 随着需求的变化,有两个职责总是同时变化,那就不必分离他们。
违反 SRP 原则
一方面我们受设计原则的指导,另一方面,我们未必要在任何时候都一成不变的遵守原则。实际开发中,因为种种原因违反 SRP 的情况并不少见。例如 jQuery 的 attr 方法 既负责赋值,又负责取值,这对 jQuery 的维护者来说会带来一些困难,但对于用户来说,却简化了使用。
SRP 的优缺点
- 优点:降低单个对象的复杂度,按照职责分解成更小的粒度,有助于代码复用,一个职责变更时,不会影响到其他职责
- 缺点: 增加总体复杂度,把对象按照职责分解成小粒度后,实际增加了对象之间的互相联系难度
2. 最少知识原则(LKP)
最少知识原则也叫迪米特法则,说的是一个软件实体应尽可能少的与其他实体发生互相作用。这里的软件实体是一个广义的概念,不仅包括系统、类、模块、函数、变量等
减少对象之间的联系
单一职责原则指导我们把对象划分成较小的粒度,这可以提高对象的可复用性,但越来越多的对象之间可能会产生错综复杂的联系,如果修改其中一个对象,可能会影响到跟他相互引用的其他对象。
最少知识原则要求我们在设计程序是,应当尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那就不要发生直接的相互联系。
设计模式中的体现
- 中介者模式:通过一个中介者对象,让所有的相关对象都通过中介者对象来通信,而不是互相引用,所以,当一个对象发生改变时,只需要通过中介者对象即可
- 外观模式:为一组子系统提供一个简单的访问入口,隔离客户与复杂子系统的联系,客户不用去了解子系统的细节,子系统内部的修改也不会影响到外部引用
3. 开放-封闭原则(OCP)
软件实体(类、模块、函数)等应该是可以扩展的,但是不可以修改
当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码,相比修改源程序,如果增加几行代码就能解决问题,那显然更加的优雅,而且增加代码并不会影响原系统的稳定
如何遵守开放-封闭原则
1. 封装变化
找出程序中将要发生变化的地方,然后把变化封装起来,通过封装变化的方式,可以把系统中稳定不变的部分和容易变化的部分隔离开。在系统演变的过程中,我们只需要替换那些容易变化的部分,如果这些部分是封装好的,那么替换起来也相对容易。
2. 放置挂钩
放置挂钩也是分离变化的一种方式,我们在程序有可能发生变化的地方放置一个挂钩,挂钩的返回结果决定了程序的下一步走向。这样一来,原本的代码执行路径上就会出现一个分叉路口,程序未来的执行方向被预埋下多种可能性
3. 使用回调函数
回调函数是一种特殊的挂钩。我们可以把一部分易于变化的逻辑封装在回调函数里,然后把回调函数当做参数传入一个稳定和封闭的函数中,当回调函数被执行时,程序就可以因为回调函数的内部逻辑不通,而产生不同的结果
开放-封闭原则的相对性
让程序保持完全封闭是不容易做到的,就算技术上做得到,也需要花费太多的时间和精力。而且代价是引入了更多的抽象层次,增加代码复杂度
可以做的
- 挑选出最容易发生变化的部分,然后构造抽象来封闭这些变化
- 在不可避免发生修改时,尽量修改相对容易修改的部分,例如对开源库来说,修改提供的 配置文件,比修改源代码来的安全又简单
4. 里氏转换原则
子类可以扩展父类的功能,但是不能改变父类原有的功能
- 子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法
- 子类可以增加自己特有的方法
- 当子类方法重载父类的方法时, 方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格
5. 依赖倒转原则
抽象不应该依赖细节,细节应该依赖于抽象,说白了就是面向接口编程,而不是面向实现编程
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
文章列表
- javascript设计模式 – 设计原则
- JavaScript设计模式–高阶函数
- Javascript 设计模式 - 01 - 原型模式
- Javascript 设计模式 - 02 - 单例模式
- Javascript 设计模式 - 03 - 建造者模式
- Javascript 设计模式 - 04 - 工厂模式
- Javascript 设计模式 - 05 - 外观模式
- Javascript 设计模式 - 06 - 代理模式
- Javascript 设计模式 - 07 - 观察者模式(发布订阅模式)
- Javascript 设计模式 - 08 - 策略模式
- Javascript 设计模式 - 09 - 命令模式
- Javascript 设计模式 - 10 - 迭代器模式
- Javascript 设计模式 - 11 - 职责链模式
- Javascript 设计模式 - 12 - 适配器模式
- Javascript 设计模式 - 13 - 模板方法
- Javascript 设计模式 - 14 - 组合模式
- Javascript 设计模式 - 15 - 享元模式
- Javascript 设计模式 - 16 - 中介者模式
- Javascript 设计模式 - 17 - 装饰者模式
- Javascript 设计模式 - 18 - 状态模式