1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="UTF-8">
5 <title>javascript高级语法14-组合模式实现</title>
6 </head>
7 <body>
8 <script>
9 //接口
10 var Interface = function(name,methods){
11 if(arguments.length != 2){
12 alert("interface must have two paramters...");
13 }
14 this.name = name;//这个是接口的名字
15 this.methods = [];//定义个空数组来转载函数名
16 for (var i = 0; i < methods.length; i++) {
17 if(typeof methods[i] != "string"){
18 alert("method name must is String ...")
19 }else{
20 this.methods.push(methods[i])
21 }
22 }
23 }
24 //定义接口的一个静态方法来实现接口与实现类的直接检验
25 //静态方法不要写成Interface.prototype.* 因为这是写到接口原型连上的
26 //我们要把静态的函数直接写到类层次上
27 Interface.ensureImplements = function(object){
28 if(arguments.length<2){
29 alert("必须最少是2个参数");
30 return false;
31 }
32 //遍历
33 for (var i = 1; i < arguments.length; i++) {
34 var inter = arguments[i];
35 //如果你是接口就必须是Interface类型的
36 if(inter.constructor != Interface){
37 throw new Error("if is interface class must is Interface type");
38 }
39 //遍历函数集合并分析
40 for (var j = 0; j < inter.methods.length; j++) {
41 var method = inter.methods[j];
42 //实现类中必须有方法名字 和 接口中所有的方法名项目
43 if(!object[method] || typeof object[method] != "function"){
44 throw new Error("实现类并没有完全实现接口中的所有方法...");
45 }
46 }
47 }
48 }
49
50 /*
51 * 组合模式
52 */
53
54 function demo(){
55 var composite = new Interface("composite",["getChildByName","add"]);
56 var student = new Interface("composite",["goToClass","finishClass"]);
57 //定义组合类
58 var compositeObj = function(name){
59 this.name = name;
60 this.type = "com"; //默认是组合类
61 var childs = new Array();
62 //得到相关的所有孩子节点
63 this.getChildByName=function(name){
64 //涉及到递归
65 var toChilds = new Array();
66 if(!name){
67 for(var i=0;i<childs.length;i++){
68 if(childs[i].type == "com"){ //组合节点
69 toChilds = toChilds.concat(childs[i].getChildByName());
70 }else{ //叶子节点
71 toChilds.push(childs[i]);
72
73 }
74 }
75 }else{
76 for(var i=0;i<childs.length;i++){
77 if(childs[i].name == name){
78 if(childs[i].type == "com"){
79 toChilds = toChilds.concat(childs[i].getChildByName());
80 break;
81 }else{
82 toChilds.push(childs[i]);
83 break;
84 }
85 }else{
86 if(childs[i].type == "com"){
87 toChilds = toChilds.concat(childs[i].getChildByName(name));
88 }
89 }
90 }
91 }
92 return toChilds;
93 }
94 //增加子节点
95 this.add = function(child){
96 childs.push(child);
97 return this;
98 }
99 //上课
100 this.goToClass = function(name){
101 var toChilds = this.getChildByName(name);
102 for(var i=0;i<toChilds.length;i++){
103 toChilds[i].goToClass(); //子类的GoToClass方法
104 }
105 }
106 //下课
107 this.finishClass = function(name){
108 var toChilds = this.getChildByName(name);
109 for(var i=0;i<toChilds.length;i++){
110 toChilds[i].finishClass(); //子类的GoToClass方法
111 }
112 }
113 //接口验证
114 Interface.ensureImplements(this,composite,student);
115 }
116 //定义叶子类
117 var studentObj = function(name){
118 this.name = name;
119 this.type = "stu";//默认是叶子
120
121 //得到相关的所有孩子节点
122 this.getChildByName=function(name){
123 if(this.name == name){
124 return this;
125 }else{
126 return null;
127 }
128 }
129 //增加子节点
130 this.add = function(child){
131 throw new Error("add 不能被初始化在叶子类中!");
132 }
133 //上课
134 this.goToClass = function(name){
135 document.write(this.name + "去上课<br>")
136 }
137 //下课
138 this.finishClass = function(name){
139 document.write(this.name + " 下课<br>")
140 }
141 Interface.ensureImplements(this,composite,student);
142 }
143
144 //测试;
145 var a = new studentObj("a");
146 var b = new studentObj("b");
147 var c = new studentObj("c");
148 var d = new studentObj("d");
149 var e = new studentObj("e");
150 var f = new studentObj("f");
151 var g = new studentObj("g");
152 var h = new studentObj("h");
153 var one = new compositeObj("一班");
154 var oneOne = new compositeObj("一班一组");
155 oneOne.add(a).add(b);
156 var oneTwo = new compositeObj("一班二组");
157 oneTwo.add(c).add(d);
158 one.add(oneOne).add(oneTwo);
159 var two = new compositeObj("二班");
160 var twoOne = new compositeObj("二班一组");
161 twoOne.add(e).add(f);
162 var twoTwo = new compositeObj("二班二组");
163 twoTwo.add(g).add(h);
164 two.add(twoOne).add(twoTwo);
165 var xuexiao = new compositeObj("新学校");
166 xuexiao.add(one).add(two);
167
168 //客户端调用API
169 xuexiao.goToClass();
170 document.write("------------------------<br>");
171 xuexiao.goToClass("一班");
172 document.write("------------------------<br>");
173 xuexiao.goToClass("二班一组");
174 document.write("------------------------<br>");
175 xuexiao.goToClass("a");
176
177 }
178 demo();
179 </script>
180 </body>
181 </html>