设计模式应该是从设计到模式,设计原则是模式的理念,知道设计原则才能更好的掌握设计模式。
设计原则
SOLID
五大设计原则
S
-单一职责原则:一个程序只做好一件事,如果功能过于复杂就拆分开,每个部分保持独立O
-开放封闭原则:对扩展开放,对修改封闭,增加需求时,扩展新代码,而非修改已有代码,这是软件设计的终极目标L
-李氏置换原则:子类能覆盖父类,父类能出现的地方子类就能出现,JS 中使用较少(弱类型&继承使用较少)I
-接口独立原则:保持接口的单一独立,避免出现“胖接口”,JS 中没有接口(typescript 例外),使用较少类似于单一职责原则,这里更关注接口D
-依赖导致原则:面向接口编程,依赖于抽象而不依赖于具体,使用方只关注接口而不关注具体类的实现,JS 中使用较少(没有接口&弱类型)
面试题考察
打车
问题
- 打车时,可以打专车或者快车。任何车都有车牌号和名称。
- 不同车价格不同,快车每公里 1 元,专车每公里 2 元。
- 行程开始时,显示车辆信息
- 行程结束时,显示打车金额(假定行程就 5 公里)
UML 类图
代码实现
class Car {
constructor(number, name) {
this.number = number;
this.name = name;
}
}
class Kuaiche extends Car {
constructor(number, name) {
super(number, name);
this.price = 1;
}
}
class Zhuanche extends Car {
constructor(number, name) {
super(number, name);
this.price = 2;
}
}
class Trip {
constructor(car) {
this.car = car;
}
start() {
console.log(`行程开始,名称: ${this.car.name}, 车牌号: ${this.car.price}`);
}
end() {
console.log('行程结束,价格: ' + this.car.price * 5);
}
}
let car = new Kuaiche(100, '桑塔纳');
let trip = new Trip(car);
trip.start();
trip.end();
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
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
停车场
问题
- 某停车场,分 3 层,每层 100 车位
- 每个车位都能监控到车辆的驶入和离开
- 车辆进入前,显示每层的空余车位数量
- 车辆进入时,摄像头可识别车牌号和时间
- 车辆出来时,出口显示器显示车牌号和停车时长
UML 类图
代码实现
// 车
class Car {
constructor(num) {
this.num = num;
}
}
// 入口摄像头
class Camera {
shot(car) {
return {
num: car.num,
inTime: Date.now(),
};
}
}
// 出口显示器
class Screen {
show(car, inTime) {
console.log('车牌号', car.num);
console.log('停车时间', Date.now() - inTime);
}
}
// 停车场
class Park {
constructor(floors) {
this.floors = floors || [];
this.camera = new Camera();
this.screen = new Screen();
this.carList = {};
}
in(car) {
// 获取摄像头的信息:号码 时间
const info = this.camera.shot(car);
// 停到某个车位
const i = parseInt((Math.random() * 100) % 100);
const place = this.floors[0].places[i];
place.in();
info.place = place;
// 记录信息
this.carList[car.num] = info;
}
out(car) {
// 获取信息
const info = this.carList[car.num];
const place = info.place;
place.out();
// 显示时间
this.screen.show(car, info.inTime);
// 删除信息存储
delete this.carList[car.num];
}
emptyNum() {
return this.floors
.map(floor => {
return `${floor.index} 层还有 ${floor.emptyPlaceNum()} 个车位`;
})
.join('\n');
}
}
// 层
class Floor {
constructor(index, places) {
this.index = index;
this.places = places || [];
}
emptyPlaceNum() {
let num = 0;
this.places.forEach(p => {
if (p.empty) {
num = num + 1;
}
});
return num;
}
}
// 车位
class Place {
constructor() {
this.empty = true;
}
in() {
this.empty = false;
}
out() {
this.empty = true;
}
}
// 测试代码------------------------------
// 初始化停车场
const floors = [];
for (let i = 0; i < 3; i++) {
const places = [];
for (let j = 0; j < 100; j++) {
places[j] = new Place();
}
floors[i] = new Floor(i + 1, places);
}
const park = new Park(floors);
// 初始化车辆
const car1 = new Car('A1');
const car2 = new Car('A2');
const car3 = new Car('A3');
console.log('第一辆车进入');
console.log(park.emptyNum());
park.in(car1);
console.log('第二辆车进入');
console.log(park.emptyNum());
park.in(car2);
console.log('第一辆车离开');
park.out(car1);
console.log('第二辆车离开');
park.out(car2);
console.log('第三辆车进入');
console.log(park.emptyNum());
park.in(car3);
console.log('第三辆车离开');
park.out(car3);
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128