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>