此系列是读JavaScript 设计模式核⼼原理与应⽤实践的自我总结.望大家指出错误,我会积极修改滴.理解方面会随着我理解的广度和深度持续更新.
OOP
对于使用JavaScript
的我开始的时候面对OOP
还有有一些些抵触的.但是现在'真香'了.我觉得OOP
有以下几个好处(不止)
- 对象的类型比看字面量对象更加可读
- 对于简单的字面量还好控制,如果是层级比较多,属性比较多的字面量,在修改的时候没有类去控制他会容易多或少属性,造成莫名其妙的错误.如果使用
get/set
方法,或者在初始化的时候使用constructor
就会大大减少此问题的出现 - 类型的判断,就可以用判断类型
instanceof
之类的方法去直接判断类型去直接计算而不是判断某个属性值来分类(鸭子类型). - 代码语义更加明确.
person.eat()
要比eat(person)
明确的多吧.
举个不按OOP
思想编写的findIndex
/**
* 在一个数组里找到一个数字的下标index
*/
function findIndex (nums: number[], needFind: number) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] === needFind) {
return i
}
}
return -1;
}
let shuzu = [{ age: 1 }, {age: 2}];
findIndex(shuzu, 2); // 自己编写的函数
// API
shuzu.findIndex(item => {
return item.age === 2;
})
这时候就可能看出Array.prototype.findIndex
的设计的精妙之处
- 调用时写法是
arr.findIndex
这样语义更加明确.减少不必要的参数.这也是oop
的时候调用其自身的方法的好处. - 参数用函数的形式使查找更加灵活.
工厂模式
简单工厂
有两个类
function Coder(name , age) {
this.name = name
this.age = age
this.career = 'coder'
this.work = ['写代码','写系分', '修Bug']
}
function ProductManager(name, age) {
this.name = name
this.age = age
this.career = 'product manager'
this.work = ['订会议室', '写PRD', '催更']
}
将两者再次进行抽象
function User(name , age, career, work) {
this.name = name
this.age = age
this.career = career
this.work = work
}
function Factory(name, age, career) {
let work
switch(career) {
case 'coder':
work = ['写代码','写系分', '修Bug']
break
case 'product manager':
work = ['订会议室', '写PRD', '催更']
break
case 'boss':
work = ['喝茶', '看报', '见客户']
case 'xxx':
// 其它工种的职责分配
...
return new User(name, age, career, work)
}
要点: 找出其中变的部分放到工厂类中,将不变的部分抽象成公共类
抽象工厂
复杂的应用往往一个工厂是不够的,如果把很多逻辑放在一个工厂函数中会违背开放封闭原则OCP
接着上面的例子,如果添加一个权限功能,boss有大权限,coder权限比较低等等.
interface Work {
personWork: () => string[];
}
interface Permission {
personPermission: () => string;
}
按角色实现他们
class User {
name: string = '';
age: number = -1;
career: string = '';
work: string[] = [];
permission: string = '';
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Boss extends User implements Work, Permission {
constructor(name: string, age: number) {
super(name, age);
this.career = 'boss';
}
personWork = () => {
let work = ['喝茶', '看报', '见客户'];
this.work = work;
return work;
};
personPermission = () => {
let permission = '啥都能看';
this.permission = permission;
return permission;
};
}
使用
let boss = new Boss('Qc', 16);
boss.personWork();
boss.personPermission();
这样的函数都符合开放封闭原则,对于以后的需求改动有着较好的可修改空间.