1.模块模式:
在立即执行函数表达式中定义的变量和方法在外界是访问不到的,只能通过其向外部提供的接口,"有限制"地访问.通过函数作用域解决了属性和方法的封装问题.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var person = ( function (){ var name = "xin" ; var age = 22; function getname(){ return name; } function getage(){ return age; } return { getname: getname, getage: getage } })(); console.log(age); // 报错:age未定义 console.log(name); // 报错:name未定义 console.log(person.age); // undefined console.log(person.name); // undefined // 只能通过person提供的接口访问相应的变量 console.log(person.getname()); // xin console.log(person.getage()); // 22 |
2.构造函数模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
function person(name,age){ this .name = name; this .age = age; } person.prototype = { constructor: person; printname: function (){ console.log( this .name); }, printage: function (){ console.log( this .age); } } var person = new person( 'xin' , 22); person.printname(); // xin person.printage(); // 22 |
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
|
function person(name,age){ this .name = name; this .age = age; }; person.prototype.printname = function (){ console.log( this .name); } function student(name,age){ // 继承 person 的属性 person.call( this ,name,age); } function create(prototype){ function f(){}; f.prototype = prototype; return new f(); } // 让student的原型指向一个对象,该对象的原型指向了person.prototype,通过这种方式继承 person 的方法 student.prototype = create(person.prototype); student.prototype.printage = function (){ console.log( this .age); } var student = new student( 'xin' ,22); student.printname(); // "xin" |
4.工厂模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function person(name, age){ var person = new object(); person.name = name; person.age = age; person.printname = function (){ console.log( this .name); }; person.printage = function (){ console.log( this .age); } return person; } var person = person( 'xin' ,22); |
5.单例模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var singleton = ( function (){ var instance; function init(){ return { // }; } return { getinstance: function (){ if (!instance){ instace = init(); } return instance; } }; })(); |
6.发布-订阅模式:
发布-订阅模式又叫做观察者模式,定义了对象之间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖与它的对象都将得到通知.
发布-订阅模式广泛应用于异步编程之中,是一种替代回调函数的方案.多个事件处理函数可以订阅同一个事件,当该事件发生后,与其相对应的多个事件处理函数都会运行
取代对象之间硬编码的通知机制,一个对象不用再显示的调用另外一个对象的某个接口,降低模块之间的耦合程度,虽然不清楚彼此的细节,但是不影响他们之间相互通信
应用
dom事件
dom事件是一种典型的发布-订阅模式,对一个dom节点的一个事件进行监听,当操作dom节点时,触发相应的事件,响应函数执行.事件函数对dom节点完全未知,不用去理会是什么事件,如何触发,执行就好.
自定义事件
指定发布者
"发布-订阅"这种关系用一个对象表示,键表示事件名,值是一个由事件处理程序组成的数组,相当于订阅者的花名册
发布消息后,遍历缓存列表,依次执行订阅者的回调函数
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
|
var eventcenter = ( function (){ // 将所有的"发布-订阅"关系放到events中 var events = {}; /** * 给事件绑定事件处理程序 * evt:事件名 * handler:事件处理程序 */ function on(evt, handler){ events[evt] = events[evt]||[]; events[evt].push({ handler:hander }); } /** * 发布消息(触发事件),并执行相应的事件处理程序 * evt:事件名 * args:给事件处理程序传递的参数 */ function fire(evt,args){ if (!events[evt]){ return ; } // 遍历事件处理程序列表,执行其中每一个事件处理程序 for ( var i=0;i<events[evt].length;i++){ events[evt][i].handler(args); } } // 使用模块模式的方式,向外界提供绑定事件处理程序和触发事件的接口 return { on: on, fire: fire } })(); |
实际应用
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
|
var event = ( function (){ var events = {}; function on(evt, handler){ events[evt] = events[evt]||[]; events[evt].push({ handler:handler }); } function fire(evt,args){ if (!events[evt]){ return ; } for ( var i=0;i<events[evt].length;i++){ events[evt][i].handler(args); } } function off(evt){ delete events[evt]; } return { on: on, fire: fire, off: off } })(); event.on( 'change' , function (val){ console.log( 'change... now val is ' + val); }); event.on( 'click' , function (val){ console.log( 'click.... now val is ' + val); }) event.fire( 'change' , 'xin' ); event.fire( 'click' , 'xin' ); event.off( 'change' );
|
7.单体模式
// 单体模式又称模块模式:用一个命名空间包含自己的所有代码的全局对象
// 简单单体模式
var timer = {
seconds: 0,
start: function () {
setinterval(() => {
this.seconds++
}, 1000);
},
dofunc() {
console.log('单体模式')
}
}
settimeout(() => {
timer.dofunc()
}, 3000);
// 单体模式表现形式2
var person = function personinfo(params) {
this.name = 'name';
this.getname = function () {
// dosomething
}
this.method = function () {
// dosomething
}
}
// 单体模式+闭包表现形式
// 模块模式
var djtest = {}
djtest.common = function () {
// dosomething
}
djtest.init = function () {
// dosomething
}
djtest.func = function () {
var val = 1
function add1(str) {
return parseint(str) + val++
}
console.log(add1(1)) // 2
return {
sumadd: function (str) {
return add1(str)
}
}
}()
console.log(djtest.func.sumadd(1)) // 3
console.log(djtest.func.sumadd(1)) // 4
console.log(djtest.func.sumadd(1)) // 5
8.策略模式
// 策略模式的定义是:定义一系列的算法/业务规则,把它们一个个封装起来,并且使它们可以相互替换。
// demo:根据级别计算奖金
var calculatebouns = function(salary,level) {
if(level === 'a') {
return salary * 4;
}
if(level === 'b') {
return salary * 3;
}
if(level === 'c') {
return salary * 2;
}
};
console.log(calculatebouns(4000,'a')); // 16000
console.log(calculatebouns(2500,'b')); // 7500
/**
* describe:
* 1,函数包含了很多if-else语句;
* 2,函数缺乏弹性,扩展需要添加新的if,else;
* 3,复用差
* */
// 策略模式改造
var obj = {
"a": function (salary) {
return salary * 4;
},
"b": function (salary) {
return salary * 3;
},
"c": function (salary) {
return salary * 2;
}
};
var calculatebouns = function (level, salary) {
return obj[level](salary);
};
console.log(calculatebouns('a',10000)); // 40000
// 优点:1. 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句。
// 2. 策略模式提供了开放-封闭原则,使代码更容易理解和扩展。
// 3. 策略模式中的代码可以复用。
// tips:开放-封闭原则:对于扩展是开放的(open for extension),对于更改是封闭的(closed for modification)
9.代理模式:
.
如对本文有疑问, 点击进行留言回复!!
网友评论