装饰模式:在不改变原类(对象)和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象。
在设计原则中,有一条,多用组合,少用继承,装饰模式正是这一原则的体现。

UML示意图:

假设自行车商店有4种自行车卖:

var ABicycle = function(){ ... };
var BBicycle = function(){ ... };
var CBicycle = function(){ ... };
var DBicycle = function(){ ... };

自行车商店需要给自行车加些配件,比如车筐,尾灯等,如果给每一类自行车创建一个子类:

var ABicycleWithBell = function(){ ... };
var BBicycleWithBasket = function(){ ... };
var CBicycleWithLight = function(){ ... };

带有铃铛的A类车,带有车筐的B类车,带有尾灯的C类车,导致的结果,就是N种配置会有4N个子类,当然不是一个可取的方法。
可以将铃铛等东西设置为实例属性,但是对于方法的扩展,比如变速等,就可以使用装饰模式。

A类自行车:

function ABicycle(){ }

ABicycle.prototype = {
wash : function(){ },
ride : function(){ },
getPrice : function(){
return 888;
}
}

铃铛:

function bicycleBell( bicycle ){
var price= bicycle.getPrice();
bicycle.bell = function(){
console.log("ding! ding!");
};
bicycle.getPrice = function(){
return price + 100;
};
return bicycle;
}

加铃铛:

var bicycleA = new ABicycle();
bicycleA = bicycleBell( bicycleA );

如果是:

bicycle.getPrice = function(){
return bicycle.getPrice() + 100;
};

会导致无限循环调用,换个方法:

function BicycleBell( bicycle ){
this.bicycle = bicycle;
} BicycleBell.prototype = {
wash : function(){
return this.bicycle.wash();
},
ride : function(){
return this.bicycle.ride();
},
getPrice : function(){
return this.bicycle.getPrice() + 100;
},
bell : function(){
console.log("ding! ding!");
}
}

包装对象,再次模拟原对象,这种方式较好的解决了对于某些需要修改并且依赖原始该方法的方法生成形式。但是有点繁琐,可以提取一下,通用继承函数:

function extend( subClass, superClass ){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype;
if( superClass.prototype.constructor === Object.prototype.constructor ){
superClass.prototype.constructor = superClass;
}
}

装饰角色:

function BicycleDecorator( bicycle ){
this.bicycle = bicycle;
}
BicycleDecorator.prototype = {
wash : function(){
return this.bicycle.wash();
},
ride : function(){
return this.bicycle.ride();
},
getPrice : function(){
return this.bicycle.ride();
}
}

使用extend:

var BicycleBell = function( bicycle ){
BicycleBell.superclass.constructor.call( this, bicycle );
}
extend( BicycleBell, BicycleDecorator ); BicycleBell.prototype.bell = function(){
console.log("ding! ding!");
}
BicycleBell.prototype.getPrice = function(){
return this.bicycle.getPrice() + 100;
}

装铃铛:

var bicycleA = new ABicycle();
bicycleA = new BicycleBell( bicycleA );

装饰者模式是为已有功能动态地添加更多功能的一种方式,把每个要装饰的功能放在单独的函数里,然后用该函数包装所要装饰的已有函数对象,因此,当需要执行特殊行为的时候,调用代码就可以根据需要有选择地、按顺序地使用装饰功能来包装对象。优点是把类(构造函数)的核心职责和装饰功能区分开了。

最新文章

  1. 在Linux下配置多线路ADSL的方法
  2. 大熊君JavaScript插件化开发------(实战篇之DXJ UI ------ ItemSelector重构完结版)
  3. Linux 小命令
  4. RPCL(Rival Penalized Competitive Learning)在matlab下的实现
  5. 如何让vim编辑器永久显示行号
  6. 分享Kali Linux 2016.2第48周虚拟机
  7. linux内核模块相关命令:lsmod,depmod,modprobe,modinfo,insmod,rmmod 使用说明
  8. linux 下使用crontab 定时打包日志并删除已被打包的日志
  9. apt局域网源搭建
  10. eclipse安装github插件egit
  11. SRM 590 DIV1
  12. [转]ASP.NET Core 1 Deploy to IIS
  13. 7.1-uC/OS-III中断管理
  14. Syntax error , insert “EnumBody” to complete EnumDeclaration
  15. Failed to set session cookie. Maybe you are using HTTP instead of HTTPS to access phpMyAdmin.
  16. 百练-16年9月推免-B题-字符串判等
  17. nginx安装最简单教程
  18. docker 私有仓库的创建
  19. Linux下KVM的图形界面管理工具(virt-manager)(桌面版)
  20. .gnet标准

热门文章

  1. vuejs常用指令
  2. 17SpringMvc_在业务控制方法中写入包装User的模型来收集参数——解决问题
  3. 【C#】【Thread】SynchronizationContext线程间同步
  4. react-native 的微信SDK辅助包,支持微信登录、微信分享、微信支付
  5. Linux常用指令---快捷键
  6. PRML读书会第四章 Linear Models for Classification(贝叶斯marginalization、Fisher线性判别、感知机、概率生成和判别模型、逻辑回归)
  7. (旧)子数涵数·PS ——素描效果
  8. webstorm调试Node的时候配置
  9. css平时写的时候注意的
  10. asp.net下载文件几种方式