设计模式1笔记

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

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

也就是说,我现在可能首先要练习的是, 分割功能时,单位不是一个函数,而应该是一个对象?

而下面提到的耦合度,主语都是对象.

image.png

image.png

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

什么是面向对象思想? 原文参考 https://blog.csdn.net/ljfzhifuwa/article/details/72235684 面向对象的历史原因是,为了解决代码的重用,维护,扩展. 由于面向过程的编程,逻辑结构过于复杂,代码晦涩难懂, 所以考虑让计算机模拟现实环境, 用人类解决问题的思路,步骤来设计应用程序.

面向对象的主要思想 : 把解决问题需要的事物分解成各个对象, 对象的目的不是为了完成一个步骤, 而是为了描述一个事物解决问题过程中的步骤和行为, 对象作为程序的基本单位, 将函数和数据封装其中, 以提高重用,灵活,扩展性. 类是模板,对象是实例,类不占内存,对象占内存.

对象的三大特性, 封装,继承,多态.(多态又是个什么意思?) 1.png

2.png 3.png 4.png 5.png 6.png

7.png

更核心的原则, 降低代码的复杂度,合理减少耦合度.

image.png 耦合性 : 就是关联性,依赖性?

image.png image.png

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

要考虑关联性, 关联性强的尽量放一起, 关联性不强的,尽量分开?

参数尽量少一点?

如果代码中 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写的这一段,拆分的单位是对象.

面向对象的编程..重用,灵活,扩展性.

image.png 预留扩展结构 在编程时,对一些有可能经常变动的地方,保持警惕,预留出一些接口.

image.png

image.png

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>

image.png image.png image.png 上图中, A,B,C,D,E就是划分出的功能,函数,对象,模块, 降低复杂度,或者分割成颗粒的意思,就是让这种模块单位变多? 因为嵌套会少? 每个模块的可读性比较强?

所谓的耦合度,从这张图上理解,就是减少线. 很明显,如果降低复杂度,那么模块有可能会增加, 而模块增加,可能会导致线条变得更多.

这也就是复杂度和耦合度之间的平衡问题.

陈老师的意思是,首先降低复杂度,分割,颗粒化,

然后再降低耦合度.

迪米特法则的意图是,不是减少上图的模块, 而是减少模块之间的线条. 理想状态可能是,每个颗粒只有一条线? 或者是,每个颗粒只有一条上线? 或者是,每个颗粒只有一条下线? image.png image.png

依赖倒置原则,, 第一,依赖接口,不依赖方法, 第二,依赖状态,不依赖彼此.

我的感受是, 首先要明白,所谓的耦合度,关联,关系,依赖, 的前提是,要知道是谁的耦合度, 是模块,对象,方法,功能的耦合度.

我们知道,一个方法在调用另一个方法, 或者一个模块调用另一个模块的时候, 是通过调用,通过传参的.

或者我们可以说,是有一个数据的流向的.

上图中的state不是一个模块,是一个状态的数据集合. 因为不是一个模块,所以其他模块(对象)与state产生的关系, 就不算是耦合度.

也就是说,有一个数据中心,然后让各个模块跟这个数据中心产生关系, 这样能极大的降低耦合度?

image.png image.png