JavaScript设计模式-16.装饰者模式(上)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>javascript 高级语法16-装饰者模式</title> 6 </head> 7 <body> 8 <script> 9 /*通过需求引出装饰者模式 10 * 11 */ 12 13 //接口 14 var Interface = function(name,methods){ 15 if(arguments.length != 2){ 16 alert("interface must have two paramters..."); 17 } 18 this.name = name;//这个是接口的名字 19 this.methods = [];//定义个空数组来转载函数名 20 for (var i = 0; i < methods.length; i++) { 21 if(typeof methods[i] != "string"){ 22 alert("method name must is String ...") 23 }else{ 24 this.methods.push(methods[i]) 25 } 26 } 27 } 28 //定义接口的一个静态方法来实现接口与实现类的直接检验 29 //静态方法不要写成Interface.prototype.* 因为这是写到接口原型连上的 30 //我们要把静态的函数直接写到类层次上 31 Interface.ensureImplements = function(object){ 32 if(arguments.length<2){ 33 alert("必须最少是2个参数"); 34 return false; 35 } 36 //遍历 37 for (var i = 1; i < arguments.length; i++) { 38 var inter = arguments[i]; 39 //如果你是接口就必须是Interface类型的 40 if(inter.constructor != Interface){ 41 throw new Error("if is interface class must is Interface type"); 42 } 43 //遍历函数集合并分析 44 for (var j = 0; j < inter.methods.length; j++) { 45 var method = inter.methods[j]; 46 //实现类中必须有方法名字 和 接口中所有的方法名项目 47 if(!object[method] || typeof object[method] != "function"){ 48 throw new Error("实现类并没有完全实现接口中的所有方法..."); 49 } 50 } 51 } 52 } 53 54 function demo(){ 55 //汽车店的接口 56 var CarShop = new Interface("CarShop",["getPrice","assemble"]); 57 var myCarShop = function(){ 58 this.getPrice = function(){ 59 document.write(15000+"<br>"); 60 } 61 this.assemble = function(){ 62 document.write("汽车组装..."+"<br>") 63 } 64 Interface.ensureImplements(this,CarShop); 65 } 66 67 var jimCarShop = new myCarShop(); 68 jimCarShop.getPrice(); 69 jimCarShop.assemble(); 70 document.write("--------------------"+"<br>") 71 72 /*新需求: 73 * 汽车还会有附属产品 音响 (k),真皮沙发(M),保险杠(N) 74 * 每一个附属的产品会影响到汽车的组装和其价格 75 * 你能想到什么办法? 76 */ 77 78 //改写接口 79 var CarShop2 = new Interface("CarShop2",["getPrice","assemble","addK","addM","addN"]); 80 var myCarShop2 = function(){ 81 var price = 150000; 82 this.getPrice = function(){ 83 document.write(price+"<br>") 84 } 85 this.assemble = function(){ 86 document.write("汽车组装"+"<br>") 87 } 88 this.addK = function(){ 89 price += 1000; 90 } 91 this.addM = function(){ 92 price += 2000; 93 } 94 this.addN = function(){ 95 price += 3000; 96 } 97 Interface.ensureImplements(this,CarShop2); 98 } 99 100 var jimCarShop2 = new myCarShop2(); 101 jimCarShop2.addK(); 102 jimCarShop2.addM(); 103 jimCarShop2.addN(); 104 jimCarShop2.getPrice(); 105 jimCarShop2.assemble(); 106 107 /*好像能成功,但是新的问题来了 108 * 你把接口全改了,可是我继承本接口的类不一定全要有音响,沙发,保险杠。 109 * 难道我要改变所有实现本接口的实现类吗? 110 * 显然是不对的。 111 */ 112 //2.如果不改变接口,那我就增加子类 113 var CarShop = new Interface("CarShop",["getPrice","assemble"]); 114 var myCarShop = function(){ 115 this.getPrice = function(){ 116 document.write(150000+"<br>"); 117 } 118 this.assemble = function(){ 119 document.write("汽车组装..."+"<br>") 120 } 121 Interface.ensureImplements(this,CarShop); 122 } 123 var myCarShopM = function(){ 124 this.getPrice = function(){ 125 document.write(150100+"<br>"); 126 } 127 this.assemble = function(){ 128 document.write("汽车组装..."+"<br>") 129 } 130 Interface.ensureImplements(this,CarShop); 131 } 132 var myCarShopK = function(){ 133 this.getPrice = function(){ 134 document.write(150200+"<br>"); 135 } 136 this.assemble = function(){ 137 document.write("汽车组装..."+"<br>") 138 } 139 Interface.ensureImplements(this,CarShop); 140 } 141 //这种方式走不通 142 /*装饰者的概念和用法: 143 * 装饰者可以为对象添加新的特性 144 * 透明的把对象包装在具有相同接口的新对象中 145 */ 146 147 } 148 // demo(); 149 function decorator(){ 150 //装饰者模式来解决需求 151 var CarShop = new Interface("CarShop",["getPrice","assemble"]); 152 //目标对象 153 var myCarShop = function(){ 154 this.getPrice = function(){ 155 return 150000; 156 } 157 this.assemble = function(){ 158 document.write("汽车组装...<br>"); 159 } 160 Interface.ensureImplements(this,CarShop); 161 } 162 //装饰类 163 var M = function(carshop){ 164 this.getPrice = function(){ 165 return 1000 + carshop.getPrice(); 166 } 167 this.assemble = function(){ 168 document.write("M组装...<br>"); 169 } 170 Interface.ensureImplements(this,CarShop); 171 } 172 var K = function(carshop){ 173 this.getPrice = function(){ 174 return 2000 + carshop.getPrice(); 175 } 176 this.assemble = function(){ 177 document.write("k组装...<br>"); 178 } 179 Interface.ensureImplements(this,CarShop); 180 } 181 var N = function(carshop){ 182 this.getPrice = function(){ 183 return 3000 + carshop.getPrice(); 184 } 185 this.assemble = function(){ 186 document.write("N组装...<br>"); 187 } 188 Interface.ensureImplements(this,CarShop); 189 } 190 191 //调用 192 193 var car =new K(new M(new myCarShop())); 194 alert(car.getPrice()); 195 car.assemble(); 196 } 197 decorator(); 198 </script> 199 </body> 200 </html>