曾读过刘伟老师的设计模式,并实现过一个小购物系统,但感觉设计模式这类型的知识还是不能够熟练运用到代码设计中,重新复习下。
设计模式原则 — SOLID
Single: 单一功能,各个部分保持独立,避免一个程序负责大于等于两个以上的功能
// bad case
function add2ThenMult3(x: number) {
return (x + 2) * 3;
}
// good case
function add2(x: number) {
return x + 2;
}
function muil3(x: number) {
return x * 3;
}
function add2ThenMult3(x: number) {
return muil3(add2(x));
}
OpenClosed: 开闭原则。对拓展开放,对修改关闭,增加新需求时可以轻松拓展而不用修改已有代码。
// *** bad case
function getMarks(chinese, math) {
// 语数两门课程成绩总和
return sum(chinese, math);
}
getMarks(chinese = 80, math = 60);
// 增加了英语科目后, 需修改原代码
function getMarks(chinese, math, english) {
// 三门课程成绩总和
return sum(chinese, math, english);
}
getMarks(chinese = 80, math = 60, english = 90);
// *** good case
function getMarks(chinese, math, otherSubjects = []) {
return sum(chinese, math, otherSubjects.reduce((a, b) => a.score + b.score));
}
getMarks(chinese = 80, math = 60);
getMarks(chinese = 80, math = 60, otherSubjects = [{ name: 'english', score: 90 }]);
Liskov Substitution: 里氏替换。在任何基类类出现的地方,子类能直接替代基类,也就是说,基类有任何修改,都不会对子类功能产生影响。
为了符合里氏替换,通常需要遵守以下原则:
子类必须实现父类抽象方法
子类不允许重写父类非抽象方法(可重载,但在js中没有重载的概念)
重载:1. 函数的参数个数不同; 2.函数的参数类型不同或者参数类型顺序不同
子类允许增加属于自己的方法
子类实现/覆盖父类方法时,方法的形参要比父类的形参定义更宽松,返回值要比父类的返回值定义更严格。更严格,例如子类比父类更严格。宽泛来说,指的是条件限制的多越严格。
Interface Segregation: 接口隔离。可参考接口隔离原则举例,写的很有意思。
单一职能和接口隔离感觉上十分相似,都使用了最小化原则。事实上,单一职能原则更多的是从单个类、函数出发,一个function负责一个功能;而接口隔离更多是从全局角度,接口角度出发设计,如上引用文章举例,work作为一个集合体,内部定义符合单一职责,但并不符合接口隔离。
Dependency Inversion:依赖倒置。即面向抽象/接口编程。可参考依赖倒置原则。面向抽象编程,可大大提高灵活度,因为抽象可继承实现,而所有实现均可替代抽象。



