一 单一职责原则
职责: 引起变化的原因
SRP原则:一个对象(方法)只做一件事
- SRP原则的应用难点就是如何去分离职责
1 何时应该分离职责
并不是所有职责都应该一一分离
- 如果随着需求变化,职责总是同时变化的就不必分离
创建xhr对象 & 发送xhr请求
- 职责的变化轴线仅当他们确定会发生变化时才有意义
虽职责耦合,但无变化迹象也不必分离
2 SRP 原则的优缺点
优点
- 降低了单个类或者对象的复杂度,按照职责把对象分解成更小的粒度,这有助于代码的复用,也有利于进行单元测试
- 当一个职责需要变更的时候,不会影响到其他的职责
缺点
- 会增加编写代码的复杂度
- 也增大了对象之间相互联系的难度
3 违反单一职责原则
受设计原则的指导,但未必要在任何时候都一成不变地遵守原则
在方便性与稳定性之间要有一些取舍
-
jQuery 的 attr 是个非常庞大的方法,既负责赋值,又负责取值
- 这对于jQuery 的维护者来说,会带来一些困难
- 但对于 jQuery 的用户来说,却简化了用户的使用
二 最少知识原则
一个软件实体(类、模块、函数、变量)应当尽可能地减少与其他实体发生相互作用
1 减少对象之间的联系
- 做法:引入第三方对象来承担对象之间的通信作用
缺点:可能会增加一些庞大到难以维护的第三者对象
2 封装在 LKP 原则中的体现
- 数据的隐藏 -- 只暴露必要的接口
- 限制变量的作用域
作用域尽可能小,对其它不相关模块的影响越小,变量被改写和发生冲突的机会越小
三 开放封闭原则
开放封闭原则是编写一个好程序的目标,其他设计原则都是达到这个目标的过程
思想:当需要改变一个程序的功能或者给这个程序增加新功能的时候,可以使用增加代码的方式,但是不允许改动程序的源代码
- 软件实体(类、模块、函数、变量)应当是可扩展的,但是不可修改
1 怎么做
找出变化的地方
1. 放置挂钩
- 在程序可能发生变化的地方放置一个挂钩,挂钩的返回结果决定程序的下一步走向
2. 使用回调函数
- 把易于变化的逻辑封装在回调函数里,作为参数传入一个稳定和封闭的函数中
ajax异步获取用户信息后处理
function getUserInfo(callback) {
$.ajax('http://xxx.com/getUserInfo', callback);
}
getUserInfo(data => {
console.log(data.name);
console.log(data.userId);
})
2 设计模式中的开放—封闭原则
发布订阅模式 模板方法模式 策略模式 代理模式 职责链模式
2.1 发布订阅模式
- 降低多个对象之间的依赖关系
- 取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口
当有新的订阅者时,发布者的代码不需要改动;改动发布者的代码时,不影响之前的订阅者
2.2 模板方法模式
通过封装变化来提高系统扩展性
- 在运用模板方法的程序中,子类的方法种类和执行顺序是不变的
将这部分逻辑抽出来放到父类的模板方法里
- 子类的方法具体实现规则是可变的
将这部分逻辑封装到子类中
- 通过增加新的子类,便能给系统增加新的功能
无需改动抽象父类及其它子类 -- 符合开放封闭原则
2.3 策略模式
大多数情况下,策略模式和模板方法是可以相互替换使用的
- 模板方法基于继承的思想
- 策略模式侧重于组合和委托
将各种算法都封装成单独的策略类,这些策略类可以被交换使用
策略和使用策略的客户代码可以分别独立进行修改而互不影响
2.4 代理模式
图片预加载
- 提供代理函数
proxyMyImage
负责图片预加载 - 之后将请求转交给
myImage
函数负责给图片设置src
myImage不知晓代理的存在,专注于自己的职责
2.5 职责链模式
let order500 = function(orderType, pay, stock) {}
let order200 = function(orderType, pay, stock) {}
let orderNormal = function(orderType, pay, stock) {}
order500.setNextSuccessor(order200).setNextSuccessor(orderNormal);
order500.passRequest(1, true, 10); // 500 元定金预购,得到 100 优惠券
增加一个新类型的订单函数时,不需要改动原有的订单函数代码,只需要在链条中增加一个新的节点
3 开放—封闭原则的相对性
- 挑选出最容易发生变化的地方,然后构造抽象来封闭这些变化
- 在不可避免发生修改的时候,尽量修改那些相对容易修改的地方
开源库: 修改它提供的配置文件,总比修改它的源代码来得简单