@@ -20,29 +20,29 @@ var b = Singleton.getInstance('seven2');
20
20
alert ( a === b ) ; // true
21
21
22
22
//或者
23
- var Singleton = function ( name ) {
23
+ var Singleton1 = function ( name ) {
24
24
this . name = name ;
25
25
}
26
26
27
- Singleton . prototype . getName = function ( ) {
27
+ Singleton1 . prototype . getName = function ( ) {
28
28
alert ( this . name ) ;
29
29
}
30
30
31
- Singleton . getInstance = ( function ( ) {
31
+ Singleton1 . getInstance = ( function ( ) {
32
32
var instance = null ;
33
33
return function ( name ) {
34
34
if ( ! instance ) {
35
- instance = new Singleton ( 'name' ) ;
35
+ instance = new Singleton1 ( 'name' ) ;
36
36
}
37
37
return instance ;
38
38
}
39
39
} ) ( ) ;
40
40
41
- var a = Singleton . getInstance ( 'seven1' ) ;
42
- var b = Singleton . getInstance ( 'seven2' ) ;
41
+ var a = Singleton1 . getInstance ( 'seven1' ) ;
42
+ var b = Singleton1 . getInstance ( 'seven2' ) ;
43
43
alert ( a === b ) ; // true
44
44
45
- //2.透明的单例模式。上述简单的单例模式并不透明,必须要知道Singleton对象有getInstance方法可以创造单例,并不能直接new
45
+ //2.透明的单例模式。上述简单的单例模式并不透明,必须要知道Singleton对象有getInstance方法可以创造单例,并不能直接new
46
46
//下面代码负责在页面中创建唯一的div节点
47
47
var CreatDiv = ( function ( ) {
48
48
var instance ;
@@ -71,12 +71,12 @@ alert(a === b); //true
71
71
//虽然上述例子实现了单例透明,但是singleton构造函数没有做到职责单一,一个方法干了两件事情,第一,是创建对象和
72
72
//执行初始化init方法,第二是保证只有一个对象
73
73
//用代理模式实现单例模式可解决此问题
74
- var CreatDiv = function ( html ) {
74
+ var CreatDiv1 = function ( html ) {
75
75
this . html = html ;
76
76
this . init ( ) ;
77
77
} ;
78
78
79
- CreatDiv . prototype . init = function ( ) {
79
+ CreatDiv1 . prototype . init = function ( ) {
80
80
var div = document . createElement ( 'div' ) ;
81
81
div . innerHTML = this . html ;
82
82
document . body . appendChild ( div ) ;
@@ -87,7 +87,7 @@ var ProxySingetonCreateDiv = (function(){
87
87
var instance ;
88
88
return function ( ) {
89
89
if ( ! instance ) {
90
- instance = new CreatDiv ( html ) ;
90
+ instance = new CreatDiv1 ( html ) ;
91
91
}
92
92
return instance ;
93
93
}
@@ -97,3 +97,102 @@ var a = new ProxySingetonCreateDiv('seven1');
97
97
var b = new ProxySingetonCreateDiv ( 'seven2' ) ;
98
98
99
99
alert ( a === b ) ;
100
+
101
+ /*前面的单例更多地接近于传统面向对象语言,是以类为中心的,比如java中,如果需要某个对象,就必须先定义一个类,对象就是从类中创建而来的,
102
+ 而javascript是“无类”语言,因此生搬单例模式并无意义*/
103
+ /*单例模式的核心是确保只有一个实例,并提供全局访问。
104
+ * 在javascript开发中,我们经常会把全局变量当做单例来使用,但全局变量很容易造成命名空间污染和变量冲突,所以可以用以下几种方式降低污染*/
105
+
106
+ //1.使用命名空间(适当地将属性和方法放入命名空间,并不会杜绝全局变量,但可以减少全局变量的数量),如:
107
+ var namespace1 = {
108
+ a :function ( ) {
109
+ alert ( 1 ) ;
110
+ } ,
111
+ b :function ( ) {
112
+ alert ( 2 ) ;
113
+ }
114
+ }
115
+ //或者动态地创建命名空间
116
+ var myapp = { } ;
117
+ myapp . namespace = function ( name ) {
118
+ var parts = name . split ( '.' ) ;
119
+ var current = myapp ;
120
+ for ( var i in parts ) {
121
+ if ( ! current [ parts [ i ] ] ) {
122
+ current [ parts [ i ] ] = { } ;
123
+ }
124
+ current = current [ parts [ i ] ] ;
125
+ }
126
+ } ;
127
+
128
+ myapp . namespace ( 'event' ) ;
129
+ myapp . namespace ( 'dom.style' ) ;
130
+ //上述代码等价于:
131
+ var myapp = {
132
+ event :{ } ,
133
+ dom :{
134
+ style :{ }
135
+ }
136
+ } ;
137
+
138
+ //2.使用闭包封装私有变量(这种方法把一些变量封装在闭包的内部,只暴露一些接口跟外界通信)
139
+ var user = ( function ( ) {
140
+ var _name = 'seven' ,
141
+ _age = 27 ;
142
+ return {
143
+ getUserInfo :function ( ) {
144
+ return _name + '-' + _age ;
145
+ }
146
+ }
147
+ } ) ( ) ;
148
+
149
+ /*惰性单例是单例模式的重点。惰性单例指的是在需要的时候才创建对象实例,
150
+ 而不是在页面加载好的时候就创建,白白浪费DOM节点。*/
151
+ //传统面向对象惰性单例模式如上述的Singleton.getInstance,我们再来回忆一次代码
152
+ Singleton . getInstance = function ( ) {
153
+ var instance = null ;
154
+ return function ( name ) {
155
+ if ( ! instance ) {
156
+ instance = new Singleton ( name ) ;
157
+ }
158
+ return instance ;
159
+ }
160
+ }
161
+
162
+ //下面介绍javascript中与全局变量结合实现惰性的单例
163
+ var createLoginLayer = ( function ( ) {
164
+ var div ;
165
+ return function ( ) {
166
+ if ( ! div ) {
167
+ div = document . createElement ( 'div' ) ;
168
+ div . innerHTML = '我是登录框' ;
169
+ div . style . display = 'none' ;
170
+ document . body . appendChild ( div ) ;
171
+ }
172
+ return div ;
173
+ }
174
+ } ) ( ) ;
175
+
176
+ //上面完成了一个可用的单例模式,但是违法了单一职责原则,创建对象和管理单例的逻辑都放在了createLoginLayer对象内部。
177
+ //把如何管理单例的逻辑从原来的代码中抽离出来,封装在getSingle内
178
+ var getSingle = function ( fn ) {
179
+ var result ;
180
+ return function ( ) {
181
+ return result || ( result = fn . apply ( this , arguments ) ) ;
182
+ }
183
+ } ;
184
+
185
+ var createLoginLayer = function ( ) {
186
+ var div = document . createElement ( 'div' ) ;
187
+ div . innerHTML = '我是登录框' ;
188
+ div . style . display = 'none' ;
189
+ document . body . appendChild ( div ) ;
190
+ return div ;
191
+ }
192
+
193
+ var createSinleLoginLayer = getSingle ( createLoginLayer ) ;
194
+
195
+ document . getElementById ( "loginBtn" ) . onclick = function ( ) {
196
+ var loginLayer = createSinleLoginLayer ( ) ;
197
+ loginLayer . style . display = 'block' ;
198
+ }
0 commit comments