文章目录
  1. 1. 原则
    1. 1.1. 开闭原则
    2. 1.2. 单一职责原则
    3. 1.3. 里氏代换原则
    4. 1.4. 迪米特法则(最小知道原则)
    5. 1.5. 依赖倒置原则
    6. 1.6. 接口分离原则
  2. 2. 设计模式
    1. 2.1. 代理模式
    2. 2.2. 单例模式
    3. 2.3. 策略模式
    4. 2.4. 工厂模式
    5. 2.5. 抽象工厂模式
    6. 2.6. 装饰模式
    7. 2.7. 观察者模式

原则

原则是指经过长期经验总结所得出的合理化的现象。
设计模式就是原则的具体实现,设计模式的六大原则

开闭原则

对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。

单一职责原则

一个方法只做一件事情,请求数据的函数你就不要渲染数据了,吃饭上厕所别用同一个地方

如我们实现获取数据,渲染数据,并且存到缓存.

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
//获取数据
function getData(callBackArr){
this.getData = function(url,param){
$.ajax({
url,
data:param,
success:function(json){
callBackArr.forEach(function(ele,inede){
ele.do(json);
})
}
})}
};

//渲染数据
function Render(dom){
this.do=function(data){
var htmStr='';
data.forEach(function(ele,index){
htmStr+='<li>'+ele.name+'</li>'
});
dom.innerHTML=htmlStr;
}
}
//缓存数据
function CacheData(type){
this.do=function(data){
localStorage.setItem(type,data);
}
}

var oC = new CacheData('list');
var oR = new Render('dom');
var gd = new getData([oC,oR]);

里氏代换原则

任何基类可以出现的地方,子类一定可以出现。通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能

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
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;
}
this.test = [];
}
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);
oS.setHeight(100);

function test(o){
while(o.getWidth() >= o.getHeight()){
o.setHeight(o.getWidth+1);
}
console.log('over');
}
test(oS);

迪米特法则(最小知道原则)

一个接口和一个方法,传入的参数越少越好。降低耦合度的同时也会让复杂程度降低。

依赖倒置原则

最常用的原则,依赖接口,不依赖方法,底层的东西不用了解,我们只需知道表现就可以

接口分离原则

把大接口拆分小接口,不能一个接口全部实现增删改查

设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。也就是本来并不存在所谓设计模式,用的人多了,也便成了设计模式。

人话来说就是按照套路做事情.

代理模式

为一个对象提供一种代理以控制对这个对象的访问

  1. 简单代理模式

    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
    var mrDeng = {
    sendFlower: function (target) {
    var flower = 'sunflower';
    target.receiveFlower(flower);
    }
    }

    var goddness = {
    mood: null,
    receiveFlower: function (flower) {
    console.log(this.mood ? 'ok' : 'get out');
    },
    changeMood: function () {
    this.mood = Math.random() > 0.8 ? true : false;
    },
    createMood: function () {
    this.changeMood();
    var self = this;
    setInterval(() => {
    self.changeMood();
    }, 300);
    }
    }
    goddness.createMood();

    //理 利用原有对象的功能 加上 自己额外的部分 去和 要访问对象互动

    var cheng = {
    proxyFlower: function (target) {
    this.listenMood(target, function () {
    mrDeng.sendFlower(target);
    });
    },
    listenMood: function (target, func) {
    var timer = setInterval(() => {
    if (target.mood) {
    func();
    clearInterval(timer);
    }
    }, 500);
    }
    }
    //代理方式
    cheng.proxyFlower(goddness);
    //不代理的方式
    mrDeng.sendFlower(goddness);
  2. 仿文件上传

    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
    //仿文件上传 
    var oDiv = document.getElementById('show');
    var oButtonArray = document.getElementsByTagName('button');
    var ProxyRequest = function (func) {
    var cache = [];
    var timer = null;
    return function () {
    cache.push(this.getAttribute('type'));
    clearTimeout(timer);
    timer = setTimeout(() => {
    func(oDiv, cache);
    }, 2000);
    }
    }
    var realChangeStyle = ProxyRequest(changeStyle);
    for (var i = 0; i < oButtonArray.length; i++) {
    oButtonArray[i].onclick = realChangeStyle;
    }
    function changeStyle(dom, typeArr) {
    var typeObj = {
    bg: ['backgroundColor', 'green'],
    cl: ['color', 'blue'],
    fs: ['fontSize', '24px'],
    fw: ['fontWeight', 'bold'],
    op: ['opacity', '0.3']
    }
    if (typeArr.constructor == Array) {
    typeArr.forEach(function (ele) {
    dom.style[typeObj[ele][0]] = typeObj[ele][1];
    })
    } else {
    dom.style[typeObj[typeArr][0]] = typeObj[typeArr][1];
    }
    }
  3. 图片预加载和懒加载

单例模式

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
//1.单例模式
// function Test(name) {
// //判断是否用new的方式来调用
// //console.log(this instanceof Test);//判断函数的原型是否在对象的原型链上 es6之前 通过call调用可以绕开
// //console.log(new.target == Test);//
// if (typeof (Test.instance) === 'object') {
// return Test.instance;
// }
// this.name = name;
// Test.instance = this;
// }
// var a = new Test();
// var b = new Test();
// console.log(a === b);

//2.进一步完美
// var Test = (function () {
// var instance = null;
// return function (name) {
// if (instance) {
// return instance;
// }
// this.name = name;
// instance = this;
// }
// })();

// var a = new Test('a');
// var b = new Test('b');

// console.log(a === b);

//3.可以使一个非单例的函数编程单例--弹窗示例
var getSingleFunc = function (func) {
var result = null;
return function () {
if (!result) {
return func.apply(this, arguments);
}
return result;
}
};

function T() {
console.log(this);
}

var singleAlert1 = getSingleFunc(T)();
var singleAlert2 = getSingleFunc(T)();
var singleAlert3 = getSingleFunc(T)();
console.log(singleAlert1 === singleAlert2 === singleAlert3)

策略模式

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
//html
<div>
用户名:<input type="test" id='userDom' name='username' />
<span id="showUser"></span>
密码:<input type="password" id="psDom" name='code' />
<span id="showPs"></span>
邮箱:<input type="text" id="emDom" name="email" />
<span id="showEm"></span>
<button id="submit">提交</button>
</div>

function Validator() {
this.cache = [];
this.warnDom = [];
}
Validator.prototype.strategies = {
isNonEmpty: function (value, errorMsg) {
if (value === "") {
return errorMsg;
}
return true;
},
maxLength: function (value, length, errorMsg) {
if (value != '' && value.length > length) {
return errorMsg;
}
return true;
},
minLength: function (value, length, errorMsg) {
if (value != '' && value.length < length) {
return errorMsg;
}
return true;
}
}

Validator.prototype.add = function (dom, showDom, strategyArr) {
var self = this;
this.warnDom.push(showDom);
strategyArr.forEach(function (ele, index) {
self.cache.push(function () {
var arr = ele.strategy.split(':');
var type = arr.shift();
arr.unshift(dom.value);
arr.push(ele.errorMsg);
var msg = self.strategies[type].apply(self, arr);
if (msg != true) {
showDom.innerText = msg;
}
return msg;

})
});
}

Validator.prototype.start = function () {
var flag = true;
this.warnDom.forEach(function (ele, index) {
ele.innerText = '';
});

this.cache.forEach(function (ele, index) {
if (ele() !== true) {
flag = false;
}
});
return flag;
}

Validator.prototype.extend = function (config) {
for (var prop in config) {
Validator.prototype.strategies[prop] = config[prop];
}
}

var validator = new Validator();
validator.extend({
isEmail: function (value, errorMsg) {
if (value != '' && value.indexOf('@') == -1) {
return errorMsg
}
return true;
},
isPhone: function (value, errorMsg) {
if (value != '' && value.length != 11) {
return errorMsg
}
return true;
}
})

submit.onclick = function () {
ProxyRequest();
}

var ProxyRequest = (function () {
validator.add(userDom, showUser, [{ strategy: 'isNonEmpty', errorMsg: '用户名不为空' }, { strategy: 'maxLength:4', errorMsg: '用户名长度不能超过4' }]);
validator.add(psDom, showPs, [{ strategy: 'isNonEmpty', errorMsg: '密码不能为空' }, { strategy: 'minLength:6', errorMsg: '密码长度不能小于6' }]);
validator.add(emDom, showEm, [{ strategy: 'isNonEmpty', errorMsg: '邮箱不能为空' }, { strategy: 'isEmail', errorMsg: '邮箱格式不正确' }]);

return function () {
if (validator.start() == true) {
//Request();
}
}
})();

工厂模式

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
function SmallPlane() {
this.width = 100;
this.height = 100
this.name = 'smallPlane';
this.blood = 100;
this.touch = function () {
this.blood -= 100;
if (this.blood == 0) {
console.log('die');
}
}
}
function BigPlane() {
this.width = 150;
this.height = 200;
this.blood = 200;
this.name = 'bigPlane';
this.touch = function () {
this.blood -= 50;
if (this.blood == 0) {
console.log('die');
}
}
}
function AttackPlane() {
this.width = 125;
this.height = 100;
this.blood = 100;
this.name = 'AttackPlanea'
this.touch = function () { };
this.attack = function () {
console.log('bultt');
}
}
function PlaneFactory(type) {
var newPlane = null;
switch (type) {
case 'SmallPlane':
newPlane = new SmallPlane();
break;
case 'BigPlane':
newPlane = new BigPlane();
break;
case 'AttackPlane':
newPlane = new AttackPlane();
break;
}
newPlane.die = function () {
console.log('boomb');
}
return newPlane;
}

抽象工厂模式

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
function PlaneFactory() {

}

// 真正定义子类工厂
PlaneFactory.prototype.SmallPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 100;
this.height = 100;
this.blood = 100;
this.name = 'SmallPlane';
}
PlaneFactory.prototype.BigPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 150;
this.height = 200;
this.blood = 200;
this.name = 'BigPlane';
}
PlaneFactory.prototype.AttackPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 100;
this.height = 125;
this.blood = 100;
this.name = 'AttackPlane';
this.attack = function () {
console.log(' biu~ biu~ biu!');
}
}

PlaneFactory.create = function (type) {
// 判断一下是否存在该类型的子类工厂
if (PlaneFactory.prototype[type] == undefined) {
throw 'no this constructor';
}
if (PlaneFactory.prototype[type].prototype.__proto__ !== PlaneFactory.prototype) {
PlaneFactory.prototype[type].prototype = new PlaneFactory();
}
var arg = Array.prototype.slice.call(arguments, 1);
var newPlane = new PlaneFactory.prototype[type](...arg);
return newPlane;
}
var oAp1 = PlaneFactory.create('AttackPlane', 10, 20);
var oAp2 = PlaneFactory.create('SmallPlane', 20, 70);

装饰模式

在不改变元对象的基础上,通过对其进行包装拓展(添加属性方法)

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
function PlaneFactory() {
//定义在这里共享一个
this.decorate_list = [];
}
//集合所有装饰方法
PlaneFactory.prototype.decorators = {
eatOneLife: function (obj) {
obj.blood += 100;
},
eatTwoLife: function (obj) {
obj.blood += 200
},
eatShrinkLife: function (obj) {
obj.blood -= 50;
}
}
//搜集对某对象的装饰描述
PlaneFactory.prototype.decorate = function (decorate) {
//this.decorate_list = ['123']; //定义在这里各用各的
this.decorate_list.push(decorate);
}

//让装饰方法作用在该对象身上
PlaneFactory.prototype.update = function () {
for (var i = 0; i < this.decorate_list.length; i++) {
this.decorators[this.decorate_list[i]] && this.decorators[this.decorate_list[i]](this);
}
}

// 真正定义子类工厂
PlaneFactory.prototype.SmallPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 100;
this.height = 100;
this.blood = 100;
this.name = 'SmallPlane';
}
PlaneFactory.prototype.BigPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 150;
this.height = 200;
this.blood = 200;
this.name = 'BigPlane';
}
PlaneFactory.prototype.AttackPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 100;
this.height = 125;
this.blood = 100;
this.name = 'AttackPlane';
this.attack = function () {
console.log(' biu~ biu~ biu!');
}
}

PlaneFactory.create = function (type) {
// 判断一下是否存在该类型的子类工厂
if (PlaneFactory.prototype[type] == undefined) {
throw 'no this constructor';
}
if (PlaneFactory.prototype[type].prototype.__proto__ !== PlaneFactory.prototype) {
PlaneFactory.prototype[type].prototype = new PlaneFactory();
}
var arg = Array.prototype.slice.call(arguments, 1);
var newPlane = new PlaneFactory.prototype[type](...arg);
return newPlane;
}
var oAp1 = PlaneFactory.create('AttackPlane', 10, 20);
var oAp2 = PlaneFactory.create('SmallPlane', 20, 70);

oAp1.decorate('eatOneLife');
oAp1.decorate('eatTwoLife');

观察者模式

作为观察者的你,订阅了一些消息,被观察者在有消息的时候就会通知你,并且把消息给到你。这个模式存在的意义就是解耦,被观察者无需关心你如何处理消息。

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
function Event() {
this.cache = {}
}
Event.prototype.on = function (type, handle) {
if (!this.cache[type]) {
this.cache[type] = [handle];
} else {
this.cache[type].push(handle);
}
}
Event.prototype.emmit = function () {
var type = arguments[0];
var arg = Array.prototype.slice.call(arguments, 1);
for (var i = 0; i < this.cache[type].length; i++) {
this.cache[type][i].apply(this, arg);
}
}
Event.prototype.empty = function (type) {
this.cache[type] = []
}
Event.prototype.remove = function (type, handle) {
this.cache[type] = this.cache[type].filter(function (ele) {
return (ele !== handle);
})
}
Event.prototype.once = function (type, handle) {

}

var oE = new Event();
function deal1(time) {
console.log('overtime1' + time);
}
oE.on('over', deal1);
function deal2(time) {
console.log('overtime2' + time);
}
oE.on('over', deal2)

oE.emmit('over', '2018-03-17');
oE.remove('over', deal2);
oE.emmit('over', 'second-2018-03-17');
文章目录
  1. 1. 原则
    1. 1.1. 开闭原则
    2. 1.2. 单一职责原则
    3. 1.3. 里氏代换原则
    4. 1.4. 迪米特法则(最小知道原则)
    5. 1.5. 依赖倒置原则
    6. 1.6. 接口分离原则
  2. 2. 设计模式
    1. 2.1. 代理模式
    2. 2.2. 单例模式
    3. 2.3. 策略模式
    4. 2.4. 工厂模式
    5. 2.5. 抽象工厂模式
    6. 2.6. 装饰模式
    7. 2.7. 观察者模式