javascript常用设计模式
寻光 2021-03-01
# 工厂模式
借助于一个“工厂”创建出某个产品的实例,具体这个产品怎样复杂,用户并不关心,用户只要这个产品的实例。
而“工厂”的作用就是为了隐藏创建产品的复杂度,只保留对外的接口。
Promise.all / Promise.race 本质上也算是工厂。
class Product {
constructor(name) {
this.name = name;
}
init() {
console.log('init!');
}
fn1() {
console.log('fn1!');
}
fn2() {
console.log('fn2!');
}
}
class Creator {
creat(name) {
return new Product(name);
}
}
//test
let p = new Creator().creat('p1');
p.init();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 单例模式
单例模式的核心就是:一个类只允许有一个有效的实例。 由于 JS 语言的限制,我们只能用闭包来实现。
class SingleObj {
private static instance: SingleObj;
private constructor() {
// error
}
public static getInstance() {
if (!SingleObj.instance) {
SingleObj.instance = new SingleObj();
}
return SingleObj.instance;
}
// other method
}
const ins = SingleObj.getInstance();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
这种模式在 Vuex 这种全局状态管理的库中用的非常多。
# 适配器模式
适配器模式比较好理解,如果有一个接口与我们的系统不兼容,那么我们只需要给这个接口加个适配器,从而达到转换的效果。
class Plug {
getInfo() {
console.log('这是一个港版的插头');
}
}
class Adapter {
constructor() {
this.plug = new Plug();
}
transform() {
//在这里对this.plug进行转换操作
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
比如 Vue 中的computed
就可以为我们提供“适配器”的效果。
比如 React 中的事件,磨平了浏览器的差异。
# 装饰模式
装饰模式可以在不改变接口的条件下为对象添加新的功能。
# 观察者模式
type Observer<T> = (val: T) => void;
class Observerable<T> {
// 可观察对象的类型
observers: Observer<T>[] = [];
subscribe(observer: Observer<T>) {
this.observers.push(observer);
}
dispatch(msg: T) {
this.observers.forEach((observer) => observer(msg));
}
}
const x = new Observerable<number>();
x.subscribe((val) => {
console.log(val);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 代理模式
class Form<T> {
constructor(private data: T) {}
get(key: string) {
return this.data[key];
}
}
function createForm<T>(data: T) {
const form = new Form<T>(data);
return (new Proxy(form, {
get(target, propKey) {
if (propKey === 'a') {
console.log('read a');
return form.get('a');
}
},
set(target, propKey, value) {
return true;
},
}) as unknown) as { [K in keyof T]: T[K] };
}
const form = createForm({
a: 1,
b: '222',
});
form.a;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29