给对象动态地增加职责的方式称作装饰者模式,它是在程序运行期间给对象动态添加职责。
一、定义
给对象动态地增加职责的方式称作装饰者模式,它是在程序运行期间给对象动态添加职责。
传统OOP编程中的继承方式存在的问题:
- 不够灵活,每次增加功能可能都需要新派生一个类;
- 基类和派生类之间容易存在强耦合性,基类的改变会影响派生类;
- 基类的实现细节对派生类可见,一定程度上破坏了封装性;
而通过装饰者模式我们可以动态地给某个对象添加一些额外的职责(功能),而不会影响这个类本身及其派生类。
二、面向对象方式的实现
核心思想:通过一个新的对象去包装原始类,新的类和原始类拥有相同接口。
实现:
1 | /*OOP方式实现*/ |
三、JavaScript的实现
JavaScript相对于强类型语言来说,它支持动态地修改对象属性,这使得装饰着模式实现更容易。
实现:
1 | /*通过保存原引用方式实现装饰者模式*/ |
技巧
使用onEventType方式给元素绑定事件时会覆盖以往的绑定函数,可以用以下方式绑定:1
2
3
4
5
6
7/*安全地通过onEventType绑定事件*/
var _ontype=Element.ontype||function(){};
Element.ontype=function(){
_ontype();
//do something new
};
以上的实现方式存在两个问题:
- 需要维护中间变量,如果装饰链较长,中间变量会变得很多;
- this被劫持,_ontype中的this指向全局变量window;
四、装饰者模式与AOP
AOP:
面向切面编程,把一些与核心业务逻辑模块无关的功能抽离出来,再通过“动态织入”的方式掺入业务逻辑中。AOP可以让核心业务模块保持纯净和高内聚性,抽离出来的模块还能较好地复用。(codepen)
1 | /*装饰者模式实现AOP*/ |
注意:
当多个before和after级联调用时,函数执行顺序是:先执行before传入的函数,后执行after函数,这与before和after的顺序无关。级联的before中先执行靠后出现的调用,after中先执行先出现的调用。
现在我们来重写安全绑定事件的方式:1
2
3
4
5/*安全地通过onEventType绑定事件*/
Element.ontype=(Element.ontype||function(){}).before(function(){
//do something new
});
技巧:
使用img的src属性上报数据:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/*使用img的src属性上报数据*/
<html>
<input type="text" id="search">
<iframe src="" frameborder="0" id="res"></iframe>
<script>
var ele=document.getElementById("search");
var img_arr=[];
ele.oninput=function(){
var img=new Image();
img.src="https://www.baidu.com/s?wd="+this.value;
document.getElementById("res").src=img.src; //非必须
};
</script>
</html>