JavaScript — 设计模式 设计原则

释放双眼,带上耳机,听听看~!

设计模式有很多,这些设计模式的出现是由准则或者说有根据的,不是平白无故出现的,下面我们就来认识一下这些设计原则。

在此以前,我想说一下,看这篇文章的读者应该都是前端工程师或者使用JS编程语言的程序员,为了结合JS语言的特性(弱类型,无接口等)有一些原则只是简单的说一下,在JS中基本不会使用,只需要你了解。

如果想要全面学习设计原则以及23种设计模式,应该选择Java而不是JS。我们只针对JS语言和前端过程中可以使用到的一些设计原则。

1  单一职责原则(S):一个程序只做一件事,如果事情过于复杂,那么就应该拆开,使得每一部分保持独立。

开发封闭原则(0):对修改封闭,对扩展开发。在遇到新的需求增加时,应该扩展新代码而不是修改原来的代码。

3  里氏代换原则(L):父类出现的地方子类也可以,也就是子类可以替换父类而且使得程序可以正常运行。

4  接口隔离原则(I):接口的设计应该保持单一功能,使用多个单一功能的接口比使用一个总接口要好。

5  依赖倒转原则(d):抽象不应该依赖于细节(实现类),细节应该依赖于抽象。高层模板不应该依赖于低层模块,应该依赖于抽象。

6  迪米特原则原则(最少知道原则):一个类对另外一个类应该了解越少越好,高内聚,低耦合。

回归上面提到的,我们是前端工程师,这后面四种作为了解内容,但是前面俩种必须知道,这是我们的重点内容。

 

单一职责和开发封闭是我们应该需要掌握的内容,回想一下自己以前写的代码是否符合这俩个准则。

举一个简单的例子来熟悉一下这俩个准则。


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
1
2function loadImg(src) {
3    return new Promise((resolve, reject) => {
4        const img = document.createElement("img");
5        img.src = src;
6        img.onload = function () {
7            resolve(img);
8        }
9        img.onerror = function () {
10            reject("图片加载错误!")
11        }
12    })
13}
14
15let src = "http://img0.imgtn.bdimg.com/it/u=276772730,3789231562&fm=26&gp=0.jpg";
16const result = loadImg(src);
17result.then((img) => {
18    console.log(`${img.width}`)
19    return img;
20}).then((img) => {
21    console.log(`${img.height}`)
22    return img
23}).catch((err) => {
24    console.log(err);
25})
26

这是一个使用promise来加载图片的例子。

这个例子里面我使用了俩个then第一个then里面打印的是img.width  第二个then里面是打印img.height。虽然看起来是很傻的俩个操作,但是我想强调的是,每一个then就相当于一个程序段,里面只需要完成自己单一的任务,当增加其他功能时,我们不需要修改上面的俩个then,再添加一个then即可。

假如我们要进行的操作是否复杂,而且十分庞大,全部都放在一个程序段里面完成,那么在后期维护上面就十分的复杂了。上面的例子也许不是很恰当,但是能够表示出意思。

单一职责和开放封闭是我们学习的重点法则。

 

接下来 我们看俩道题目,来帮助大家理解面向对象设计原则。 

 

JavaScript -- 设计模式 设计原则JavaScript -- 设计模式 设计原则

大家觉得这题目如何,假如需要你设计你该如何设计了?思考一下,然后在继续看下面内容。

首先,我们可以知道任何车都有车牌号和名称,也就是说我们可以抽象一个车作为父类,包含车牌号和名称。因为价格,快车和专车不一样,我们可以把价格属性放到子类(快车和专车)中。

大家现在想一下,行程和是什么车有关系吗?快车有行程,专车也有行程,即行程应该和父类关联起来,而不是子类。最后一点,打车金额是行程的还是车的?  很明显应该是行程的。

画出UML图

JavaScript -- 设计模式 设计原则

写出JS代码


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
30
31
32
33
34
35
36
1class Car {
2    constructor(name, number) {
3        this.name = name;
4        this.number= number;
5    }
6}
7
8class KuaiChe extends Car {
9    constructor(name, number) {
10        super(name, number);
11        this.price = 1;
12    }
13}
14class ZhuanChe extends Car {
15    constructor(name, number) {
16        super(name, number);
17        this.price = 2;
18    }
19}
20class Trip {
21    constructor(c) {
22        this.car = c;
23    }
24    start() {
25        console.log(`${this.car.name}车为你服务,车牌号为${this.car.number}`)
26    }
27    end() {
28        console.log(`你需要支付${this.car.price * 5}元`)
29    }
30}
31
32const c = new KuaiChe("奔驰", 100);
33const t = new Trip(c);
34t.start();
35t.end();
36

JavaScript -- 设计模式 设计原则

 

下面题目会有难度

JavaScript -- 设计模式 设计原则

这道题目相较于上面一道题目难度提升很大。

从第一句话就应该了解到,我们需要建立停车场类(park) 层类(floor) 停车位类(place)

第二句话,我可以得到每个车位应该有俩个方法(in out)来表示车的驶入和离开,还应该在停车位类上面设置一个标志位isEmpty表示是否是空的。

第三句话:我们应该知道停车场里面有一个方法用于计算机每一层的空位,那么计算每一层的空位应该谁来做比较好?很明显应该是floor类来做。

第四句话:我们应该知道还需要一个摄像头类,当车辆进入后,用来记录车牌号和时间,记录的值应该保存在停车场里面。

第五句话:我们应该需要一个显示器类,当车辆出来时,显示车牌号和停车时长。

UML类图如下:

JavaScript -- 设计模式 设计原则

我们用代码实现一下


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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
1class Car { //车类
2    constructor(number) {
3        this.number = number; //车牌号
4    }
5}
6
7class Camera {//照相机类
8    constructor() {};
9    shot(car) {
10        return {
11            number: car.number,
12            cTime: Date.now()
13        }
14    }
15}
16class Screen { //显示器
17    constructor() {};
18    show(obj) {
19        console.log(`车牌号${obj.number}准备离开,停车时间${Date.now()-obj.cTime}`)
20    }
21}
22
23class Place { // 车位
24    constructor() {
25        this.isEmpty = true;
26    }
27    in() { //有车进入
28        this.isEmpty = false;
29    }
30    out() { //有车出去
31        this.isEmpty = true;
32    }
33}
34
35class Floor { // 层类
36    constructor(index, places) {
37        this.index = index;
38        this.places = places;
39    }
40    calEmptyPlace() { //计算每一层空位
41        let cnt = 0;
42        this.places.forEach((item) => {
43            if (item.isEmpty) cnt++;
44        })
45        return cnt;
46    }
47}
48class Park { //停车场
49    constructor(floors) {
50        this.floors = floors;
51        this.camera = new Camera();
52        this.screen = new Screen();
53        this.car = {};
54    }
55    calEmpty() {
56        this.floors.forEach((item) => {
57            console.log(`第${item.index}层的空位是${item.calEmptyPlace()}个\n`)
58        })
59    }
60    in(car) {
61        this.calEmpty(); //显示有多少车辆
62
63        const info = this.camera.shot(car); //拍照
64        //停在那里 这个由车主自己决定
65        const index = 0; //假设第一层
66        const pot = parseInt((Math.random() * 100) % 100);
67        const place = this.floors[index].places[pot]; //取车位
68      
69        place.in(); //进入
70
71        this.car[info.number] = {
72            info,
73            place
74        }//保存拍照信息
75    }
76    out(car) {
77        this.screen.show(this.car[car.number].info); //显示
78        this.car[car.number].place.out();
79    }
80}
81
82const floors = [];
83for (let i=0; i<3; i++) {
84    let places = [];
85    for (let j=1; j<=100; j++) {
86        places[j] = new Place();
87    }
88    floors[i] = new Floor(i+1, places);
89}
90
91const p = new Park(floors);
92
93const car1 = new Car(1);
94const car2 = new Car(2);
95const car3 = new Car(3);
96
97console.log("第一辆车来了")
98p.in(car1);
99console.log("第二辆车来了")
100p.in(car2);
101console.log("第一辆车走了")
102p.out(car1);
103console.log("第二辆车走了")
104p.out(car2);
105console.log("第三辆车来了")
106p.in(car3);
107console.log("第三辆车走了")
108p.out(car3);
109
110

看一下效果如何

JavaScript -- 设计模式 设计原则

预期效果一样。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++迭代器

2022-1-11 12:36:11

安全漏洞

预警Gitlab Wiki API 远程代码执行漏洞CVE-2018-18649

2018-12-28 19:15:56

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索