Skip to content

Commit a9a0619

Browse files
组合模式
1 parent 6eb1391 commit a9a0619

4 files changed

Lines changed: 208 additions & 258 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
组合模式可以使用树形方式创建对象的结构
2+
可以把相同的操作应用在组合对象和单个对象上,可以忽略组合对象和单个对象之间的差别,用一致的方式来处理它们
3+
4+
<body>
5+
<button id="button">按我</button>
6+
</body>
7+
<script>
8+
var MacroCommand = function(){
9+
return {
10+
commandsList: [],
11+
add: function( command ){
12+
this.commandsList.push( command );
13+
},
14+
execute: function(){
15+
for ( var i = 0, command; command = this.commandsList[ i++ ]; ){
16+
command.execute();
17+
}
18+
}
19+
}
20+
};
21+
var openAcCommand = {
22+
execute: function(){
23+
console.log( '打开空调' );
24+
}
25+
};
26+
/**********家里的电视和音响是连接在一起的,所以可以用一个宏命令来组合打开电视和打开音响的命令*********/
27+
var openTvCommand = {
28+
execute: function(){
29+
console.log( '打开电视' );
30+
}
31+
};
32+
var openSoundCommand = {
33+
execute: function(){
34+
console.log( '打开音响' );
35+
}
36+
};
37+
var macroCommand1 = MacroCommand();
38+
macroCommand1.add( openTvCommand );
39+
macroCommand1.add( openSoundCommand );
40+
/*********合并 关门、打开电脑和登录QQ 的命令****************/
41+
var closeDoorCommand = {
42+
execute: function(){
43+
console.log( '关门' );
44+
}
45+
};
46+
var openPcCommand = {
47+
execute: function(){
48+
console.log( '开电脑' );
49+
}
50+
};
51+
var openQQCommand = {
52+
execute: function(){
53+
console.log( '登录QQ' );
54+
}
55+
};
56+
var macroCommand2 = MacroCommand();
57+
macroCommand2.add( closeDoorCommand );
58+
macroCommand2.add( openPcCommand );
59+
macroCommand2.add( openQQCommand );
60+
/*********现在把所有的命令组合成一个“超级命令”**********/
61+
var macroCommand = MacroCommand();
62+
macroCommand.add( openAcCommand );
63+
macroCommand.add( macroCommand1 );
64+
macroCommand.add( macroCommand2 );
65+
/*********最后给遥控器绑定“超级命令”**********/
66+
var setCommand = (function( command ){
67+
document.getElementById( 'button' ).onclick = function(){
68+
command.execute();
69+
}
70+
})( macroCommand );
71+
72+
// 打开空调
73+
// 打开电视
74+
// 打开音响
75+
// 关门
76+
// 开电脑
77+
// 登录QQ
78+
</script>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
<script>
3+
/**
4+
* Folder
5+
*/
6+
var Folder = function( name ){
7+
this.name = name;
8+
this.files = [];
9+
};
10+
Folder.prototype.add = function( file ){
11+
this.files.push( file );
12+
};
13+
Folder.prototype.scan = function(){
14+
console.log( '开始扫描文件夹: ' + this.name );
15+
for ( var i = 0, file, files = this.files; file = files[ i++ ]; ){
16+
file.scan();
17+
}
18+
};
19+
/**
20+
* File
21+
*/
22+
var File = function( name ){
23+
this.name = name;
24+
};
25+
File.prototype.add = function(){
26+
throw new Error( '文件下面不能再添加文件' );
27+
};
28+
File.prototype.scan = function(){
29+
console.log( '开始扫描文件: ' + this.name );
30+
};
31+
32+
// 处理文件和文件夹层级关系
33+
var folder = new Folder( '学习资料' );
34+
var folder1 = new Folder( 'JavaScript' );
35+
var folder2 = new Folder ( 'jQuery' );
36+
var folder3 = new Folder( 'Nodejs' );
37+
var file1 = new File( 'JavaScript 设计模式与开发实践' );
38+
var file2 = new File( '精通jQuery' );
39+
var file3 = new File( '重构与模式' );
40+
var file4 = new File( '深入浅出Node.js' );
41+
var file5 = new File( 'JavaScript 语言精髓与编程实践' );
42+
43+
folder1.add( file1 );
44+
folder2.add( file2 );
45+
folder3.add( file4 );
46+
47+
folder.add( folder1 );
48+
folder.add( folder2 );
49+
folder.add( file3 );
50+
folder.add( folder3 );
51+
folder.add( file5 );
52+
53+
folder.scan();
54+
55+
</script>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
组合对象保存了它下面的子节点的引用,这是组合模式的特点,此时树结构是从上至下的
2+
但有时候我们需要在子节点上保持对父节点的引用,比如在组合模式中使用职责链时,有可能需要让请求从子节点往父节点上冒泡传递
3+
还有当我们删除某个文件的时候,实际上是从这个文件所在的上层文件夹中删除该文件的
4+
<script type="text/javascript">
5+
/**
6+
* Folder
7+
* parent & remove
8+
*/
9+
var Folder = function( name ){
10+
this.name = name;
11+
this.parent = null; //增加this.parent 属性
12+
this.files = [];
13+
};
14+
Folder.prototype.add = function( file ){
15+
file.parent = this; //设置父对象
16+
this.files.push( file );
17+
};
18+
Folder.prototype.scan = function(){
19+
console.log( '开始扫描文件夹: ' + this.name );
20+
for ( var i = 0, file, files = this.files; file = files[ i++ ]; ){
21+
file.scan();
22+
}
23+
};
24+
Folder.prototype.remove = function(){
25+
if ( !this.parent ){ //根节点或者树外的游离节点
26+
return;
27+
}
28+
for ( var files = this.parent.files, l = files.length - 1; l >=0; l-- ){
29+
var file = files[ l ];
30+
if ( file === this ){
31+
files.splice( l, 1 );
32+
}
33+
}
34+
};
35+
/**
36+
* File
37+
* parent & remove
38+
*/
39+
var File = function( name ){
40+
this.name = name;
41+
this.parent = null;
42+
};
43+
44+
File.prototype.add = function(){
45+
throw new Error( '不能添加在文件下面' );
46+
};
47+
48+
File.prototype.scan = function(){
49+
console.log( '开始扫描文件: ' + this.name );
50+
};
51+
52+
File.prototype.remove = function(){
53+
if ( !this.parent ){ //根节点或者树外的游离节点
54+
return;
55+
}
56+
for ( var files = this.parent.files, l = files.length - 1; l >=0; l-- ){
57+
var file = files[ l ];
58+
if ( file === this ){
59+
files.splice( l, 1 );
60+
}
61+
}
62+
};
63+
64+
var folder = new Folder( '学习资料' );
65+
var folder1 = new Folder( 'JavaScript' );
66+
var file1 = new Folder ( '深入浅出Node.js' );
67+
68+
folder1.add( new File( 'JavaScript 设计模式与开发实践' ) );
69+
folder.add( folder1 );
70+
folder.add( file1 );
71+
folder1.remove(); //移除文件夹
72+
73+
folder.scan();
74+
75+
</script>

0 commit comments

Comments
 (0)