极客学院 设计模式课程

设计模式存在的根本原因是为了代码复用,增加可维护性,有如下原则:

  • 【开闭原则】对扩展开放,对修改关闭。
  • 【里氏转换原则】子类继承父类,单独掉完全可以运行。
  • 【依赖倒转原则】引用一个对象,如果这个对象有底层的类型,直接引用底层。
  • 【接口隔离原则】每一个接口应该是一种角色。
  • 【合成/聚合复用原则】新的对象应使用一些已有的对象,使之成为新对象一部分。
  • 【迪米特原则】一个对象应对其他对象有尽可能少的了解。

单例模式

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

/*模式作用
*1.模块间通信。
*2.系统中某个类的对象只能存在一个。
*3.保护自己的属性和方法。
*/

/*注意事项
*1.注意this的使用。
*2.闭包容易造成内存泄漏,不需要的赶快干掉。
*3.注意new的成本。(继承)
*/

var xiaowang = (function (argument) {
var xiaowangjia = function(message){
this.menling = message;
}
var men;
var info = {
sendMessage:function (message) {
if(!men){
men = new xiaowangjia(message);
};
return men;
}
};

return info;
})();

var xiaoli = {
callXiaowang:function(msg){
var _xxw = xiaowang.sendMessage(msg);
alert(_xxw.menling);
_xxw = null;
}
};

/*用户使用区域*/
xiaoli.callXiaowang('didi');
xiaoli.callXiaowang('hello');//我自己添加的测试

单例模式 按钮实例

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
//该案例只是概念,无法正常运行
// 页面上有6个按钮
//a b c => top
//d e f => banner

var top = {
init:function(){
this.render();
this.bind();
},
a:4,
render:function(){
var me = this;
me.btna = $('#a');
},
bind:function(){
var me = this;
me.btna.click(function(){
me.test();
});
},
test:function(){
a = 5;
}
}

var banner = {
init:function(){
this.render();
this.bind();
},
a:4,
render:function(){
var me = this;
me.btna = $('#d');
},
bind:function(){
var me = this;
me.btna.click(function(){
me.test();
});
},
test:function(){
top.a = 6;
}
}

top.init();
banner.init();

构造函数模式

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
/*模式作用
*1.用于创建特定类型的对象。
*2.第一次声明的时候给对象赋值。
*3.自己声明构造函数,赋予属性和方法。
*/

/*注意事项
*1.声明函数的时候处理业务逻辑。
*2.区分和单例的区别,配合单例实现初始化。
*3.构造函数大写字母开头。(建议)
*/

function zaomen(huawen){
var _huawen="普通";
if(huawen){
_huawen = huawen;
}
this.suo = '普通';
this.huawen = _huawen;
this.create = function(){
return '【锁头】' + this.suo + '【花纹】' + this.huawen
}
}

var xiaozhang = new zaomen();
alert("xiaozhang" + xiaozhang.create());

var xiaoli = new zaomen('绚丽');
alert('xiaoli' + xiaoli.create());

建造者模式

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
  /*模式作用
*1.分步创建一个复杂的对象。
*2.解耦封装过程和具体创建的组件。
*3.无需关心组件如何组装。
*/

/*注意事项
*1.一定要一个稳定的算法进行支持。
*2.加工工艺是暴露的。
*/

function Fangzi(){
this.woshi = "";
this.keting = "";
this.chufang = "";
}

function Baogongtou(){
this.gaifangzi = function(gongren){
gongren.jian_woshi();
gongren.jian_keting();
gongren.jian_chufang();

}

}

function Gongren(){
this.jian_woshi = function(){
alert("卧室盖好了");
}
this.jian_keting = function(){
alert("客厅盖好了");
}
this.jian_chufang = function(){
alert("厨房盖好了");
}

this.jiaogong = function(){
var _fangzi = new Fangzi();
_fangzi.woshi = "OK";
_fangzi.keting = "OK";
_fangzi.chufang = "OK";
return _fangzi;
}
};

var gongren = new Gongren;
var baogongtou = new Baogongtou();
baogongtou.gaifangzi(gongren);

var myfangzi = gongren.jiaogong();
console.log(myfangzi);

工厂模式

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
/*模式作用
*1.对象的构建十分复杂。
*2.需要依赖具体的环境创建不同的实例。
*3.处理大量具有相同属性的小对象。
*/

/*注意事项
*1.不能滥用工厂,有时候仅仅是给代码增加复杂度。
*/

var gongchang = {};

gongchang.chanyifu = function(argument){
this.gongren = 50;
alert('我们有' + this.gongren + '个工人。')

}
gongchang.chanxie = function(){
alert('生产鞋子');
}
gongchang.yunshu = function(){
alert('运输');
}
gongchang.changzhang = function(para){
return new gongchang[para]();
}

var me = gongchang.changzhang('chanxie');

代理模式

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
/*模式作用
*1.远程代理(一个对象将不同空间的对象进行局部代理)。
*2.虚拟代理(根据需要创建开销代价很大的对象如渲染网页暂时用占位符代替真图)。
*3.安全代理(控制真是对象的访问权限)。
*4.智能指引(调用对象代理处理另外一些事情如垃圾回收机制)。
*/

/*注意事项
*1.不能滥用代理,有时候仅仅是给代码增加复杂度。
*/

function maijia(argument){
this.name = '小明' ;
}

function zhongjie(){

}

zhongjie.prototype.maifang = function(){
new fangdong(new maijia()).maifang("20万");
};

function fangdong(maijia){
this.maijia_name = maijia.name;
this.maifang = function(money){
alert('收到钱');
}

}
var zhongjianshang = new zhongjie;
zhongjianshang.maifang();

司令模式

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
/*模式作用
*1.将函数的封装、请求、调用结合为一体。
*2.调用具体的函数解耦命令对象与接收对象。
*3.提高程序模块化的灵活性。
*/

/*注意事项
*1.不需要接口一致,直接调用函数即可,以免造成浪费。
*/

var lian = {};
lian.paobing = function(pao_num){
alert(pao_num + '炮' + '开始战斗');
}
lian.bubing = function(bubing_num){
alert(bubing_num + '人' + '开始战斗');
}
lian.lianzhang = function(mingling){
lian[mingling.type](mingling.num);
}

lian.lianzhang({
type:'paobing',
num:100
});

lian.lianzhang({
type:'bubing',
num:500
})

极客学院-总结

  极客学院的js设计模式教程的案例都是为了便于理解和解构出来的,但是我认为这样就是耍流氓,原理都懂但是没有实战就是纸上谈兵而已,所以我看完之后其实收获不大(能力有限(:з」∠)


Plurasight.com - JavaScript Design Patterns

Chaining pattern 链式模式

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
//这种方法就是JQuery常见的构造方法

var Calc = function(start){
this.add = function(x){
start = start + x;
return this;
};

this.multiply = function(x){
start = start * x;
return this;
};

this.equals = function(callback){
callback(start);
return this;
};
}

new Calc(0)
.add(1)
.add(2)
.multiply(3)
.equals(function(result){
console.log(result);
});

Creating Observerable Properties 观察者模式

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
var Book = function(name,price){
var priceChanging = [];
var priceChanged = [];

this.name = function(val){
return name;
};

this.price = function(val){
if(val !== undefined && val !== price){
for(var i = 0; i < priceChanging.length;i++){
if(!priceChanging[i](val)){
return price;
}
}
price = val;
for(var i = 0; i < priceChanged.length; i++){
priceChanged[i](this);
}
}
return price;
};

this.onPriceChanging = function(callback){
priceChanging.push(callback);
};

this.onPriceChanged = function(callback){
priceChanged.push(callback);
};
}

/*****************/
/*用户使用时的代码*/
/****************/

/*
*Book CLass
*传入书名和价格
*改变价格是预判条件的 onPriceChanging => function
*/

var book = new Book('JavaScript: The Good Parts',23.99);

book.onPriceChanging(function(price){
if(price > 100){
console.log('系统错误,价格超过了预估值!');
return false;
}
return true;
});

book.onPriceChanged(function(b){
console.log('书本的价格已经改变为:¥' + b.price());
});

book.price(19.99);

book.price(20);

JavaScript Design Patterns - 总结

  观察者模式非常实用,可以在外部补充内部代码的不足,从外部完成对内部运行的一些代码补充,非常方便。
  JQuery的链式模式我并没有怎么用,但是理论明白还是觉得非常方便的,threejs的add函数也是用相似的方法写的。

总结

  设计模式其实所有面向对象语言都存在的,四人帮(gang of four)就有著名的著作
  Jjs在设计模式的实现和其他语言大相径庭,因为js的理念是万物皆对象,无论是变量还是函数都可以升级为类,当然现在ES6标准已经加入了语法糖可以用类似Java的方法来构造类了。