回过头来重新理解一下, 如果要学设计模式, 就要先理解设计原则, 而学习设计模式和设计原则, 首先要明白大前提是,面向对象的编程. 而面向对象的思想是, 把解决问题相关的事物分解成各个对象,不是为了实现一个步骤, 而是描述解决问题过程中,事物的步骤和行为. 对象作为程序的基本单位, 将数据和函数封装在其中.
也就是说,我现在可能首先要练习的是, 分割功能时,单位不是一个函数,而应该是一个对象?
而下面提到的耦合度,主语都是对象.


技术的黑匣子?
设计模式 : 前人总结出的套路,
规律,公式,套路

什么是面向对象思想? 原文参考 https://blog.csdn.net/ljfzhifuwa/article/details/72235684 面向对象的历史原因是,为了解决代码的重用,维护,扩展. 由于面向过程的编程,逻辑结构过于复杂,代码晦涩难懂, 所以考虑让计算机模拟现实环境, 用人类解决问题的思路,步骤来设计应用程序.
面向对象的主要思想 : 把解决问题需要的事物分解成各个对象, 对象的目的不是为了完成一个步骤, 而是为了描述一个事物解决问题过程中的步骤和行为, 对象作为程序的基本单位, 将函数和数据封装其中, 以提高重用,灵活,扩展性. 类是模板,对象是实例,类不占内存,对象占内存.
对象的三大特性, 封装,继承,多态.(多态又是个什么意思?)



更核心的原则, 降低代码的复杂度,合理减少耦合度.
耦合性 : 就是关联性,依赖性?

通常是通过增加耦合度降低复杂度

要考虑关联性, 关联性强的尽量放一起, 关联性不强的,尽量分开?
参数尽量少一点?
如果代码中 if else for 这种嵌套比较多, 就表示 复杂度比较高? 而耦合度指的是以对象(或者函数)为单位(也可以说是模块)时, 与其他对象的关联性,或者互相关联的对象的数量? 越多表示耦合度越高.
想办法,尽量减少重复的判断?
下面是没有拆分,全写一起,复杂度比较高的写法.
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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>dddd</title>
<style type="text/css">
</style>
</head>
<body>
<ul></ul>
<button id="btn">updata</button>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
//按照单一职责原则
//获取数据
function GetData (callbackArr) {
this.getData = function (url,param) {
$.ajax({
url:url,
data: param,
success : function (json) {
callbackArr.forEach(function (ele,index){
ele.do(json);
})
}
})
}
}
var oG = new GetData([oR,oC]);
//根据数据渲染
function Render (dom) {
this.do = function (data){
var arr = JSON.parse(data);
var htmlStr = '';
arr.forEach(function (ele,item) {
htmlStr += '<li>'+ ele.name +'</li>';
});
dom.innerHTML = htmlStr;
}
}
var oR = new Render(ul);
oR.do(data);
//缓存数据
function CacheData (type) {
this.do = function (data){
localStorate.setItem(type,data)
}
this.returnCacheData = function () {
return localStorage.getItem(type);
}
}
var oC = new CacheData('list');
// 如果离线, 从缓存获取数据, 点击也不请求网络数据.
// 如果在线 , 通过缓存获取数据 点击请求网络数据
// 在线
if (navigator.onLine) {
if(oC.returnCacheData()){
oR.do(oC.returnCacheData());
}else{
oG.getData();
}
}else {
//离线
if(oC.returnCacheData()) {
oR.do(oC.returnCacheData());
}else {
oG.getData();
}
}
//上面这一段是有重复判断的.可以改成下面这样.
// 复杂度就降低了.
if(oC.returnCacheData()) {
if(navigator.onLine){
oR.do(oC.returnCacheData());
}else{
oG.getData();
}
}else {
oG.getData();
}
oBtn.onclick = function () {
oG.getDate('xxx','page=2')
}
</script>
</body>
</html>
看完这一段代码,最大的感触是,
我目前的段位,只能做到用函数的方式,把功能拆分出来,
而cto写的这一段,拆分的单位是对象.
面向对象的编程..重用,灵活,扩展性.
预留扩展结构
在编程时,对一些有可能经常变动的地方,保持警惕,预留出一些接口.


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
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>dddd</title>
<style type="text/css">
</style>
</head>
<body>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script type="text/javascript">
// 里氏代换原则 感受一下
// 矩形
function Rectangle () {
this.width = 0;
this.height = 0;
this.setWidth = function (width) {
this.width = width
}
this.setHeight = function (height) {
this.height = height
}
this.getWidth = function () {
return this.width
}
this.getHeight = function () {
return this.height
}
}
//生成 方形
Square.prototype = new Rectangle();
function Square () {
this.setWidth = function (width) {
this.width = width;
this.height = width;
};
this.setHeight = function (height) {
this.setWidth(height);
}
}
// 在子类修覆盖了父类, 违背了 里氏代换原则?
// 比如下面
// 父类可以,但子类不可以
// 父类
var oR = new Rectangle();
oR.setWidth(200);
oR.setHeight(100);
// 子类
var oS = new Square();
oS.setWidth(200);
function Resize (o) {
while (o.getHeight() <= o.getWidth()){
o.setHeight(o.getWidth() + 1);
}
console.log('over',o);
}
Resize(oR);
// Resize(oS);//这是不行的, 因为一旦修改了height, width会跟着改变.
//考验的是类关系之间的设计的能力
</script>
</body>
</html>
上图中,
A,B,C,D,E就是划分出的功能,函数,对象,模块,
降低复杂度,或者分割成颗粒的意思,就是让这种模块单位变多?
因为嵌套会少? 每个模块的可读性比较强?
所谓的耦合度,从这张图上理解,就是减少线. 很明显,如果降低复杂度,那么模块有可能会增加, 而模块增加,可能会导致线条变得更多.
这也就是复杂度和耦合度之间的平衡问题.
陈老师的意思是,首先降低复杂度,分割,颗粒化,
然后再降低耦合度.
迪米特法则的意图是,不是减少上图的模块,
而是减少模块之间的线条.
理想状态可能是,每个颗粒只有一条线?
或者是,每个颗粒只有一条上线?
或者是,每个颗粒只有一条下线?

依赖倒置原则,, 第一,依赖接口,不依赖方法, 第二,依赖状态,不依赖彼此.
我的感受是, 首先要明白,所谓的耦合度,关联,关系,依赖, 的前提是,要知道是谁的耦合度, 是模块,对象,方法,功能的耦合度.
我们知道,一个方法在调用另一个方法, 或者一个模块调用另一个模块的时候, 是通过调用,通过传参的.
或者我们可以说,是有一个数据的流向的.
上图中的state不是一个模块,是一个状态的数据集合. 因为不是一个模块,所以其他模块(对象)与state产生的关系, 就不算是耦合度.
也就是说,有一个数据中心,然后让各个模块跟这个数据中心产生关系, 这样能极大的降低耦合度?
