JavaScript设计模式(装饰者模式)
一、模拟传统面向对象语言的装饰者模式:
// 首先是原始的飞机类
var Plane = function(){
}
Plane.prototype.fire = function(){
console.log( '发射普通子弹' );
} // 接下来增加两个装饰类,分别是导弹和原子弹:
var MissileDecorator = function( plane ){
this.plane = plane;
}
MissileDecorator.prototype.fire = function(){
this.plane.fire();
console.log( '发射导弹' );
} var AtomDecorator = function( plane ){
this.plane = plane;
}
AtomDecorator.prototype.fire = function(){
this.plane.fire();
console.log( '发射原子弹' );
} // 最后看看测试结果
var plane = new Plane();
plane = new MissileDecorator( plane );
plane = new AtomDecorator( plane );
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹
二、装饰者也是包装器
三、回到JavaScript的装饰者
var plane = {
fire: function(){
console.log( '发射普通子弹' );
}
}
var missileDecorator = function(){
console.log( '发射导弹' );
}
var atomDecorator = function(){
console.log( '发射原子弹' );
}
var fire1 = plane.fire;
plane.fire = function(){
fire1();
missileDecorator();
}
var fire2 = plane.fire;
plane.fire = function(){
fire2();
atomDecorator();
}
plane.fire();
// 分别输出: 发射普通子弹、发射导弹、发射原子弹
四、用AOP装饰函数
Function.prototype.before = function( beforefn ){
// 保存原函数的引用
var __self = this;
// 返回包含了原函数和新函数的"代理"函数
return function(){
// 执行新函数,且保证this不被劫持,新函数接受的参数
// 也会被原封不动地传入原函数,新函数在原函数之前执行
beforefn.apply( this, arguments );
return __self.apply( this, arguments ); // 执行原函数并返回原函数的执行结果, // 并且保证this不被劫持
}
}
Function.prototype.after = function( afterfn ){
var __self = this;
return function(){
var ret = __self.apply( this, arguments );
afterfn.apply( this, arguments );
return ret;
}
};
// 实例1:
document.getElementById = document.getElementById.before(function() {
alert (1);
});
var button = document.getElementById('button');
console.log(button) // 实例2(改造window.onload):
window.onload = function(){
alert (11);
}
window.onload = ( window.onload || function(){} ).before(function(){
alert (22);
}).after(function(){
alert (33);
}).after(function(){
alert (44);
});
var before = function( fn, beforefn ){
return function(){
beforefn.apply( this, arguments );
return fn.apply( this, arguments );
}
}
var a = before( function(){
alert (3)
}, function(){
alert (2)
}
);
a = a();
五、AOP的应用实例
5.1:假设现在我们需要点击一个按钮后既要负责打开登录浮层,和负责数据上报,我们看到在showLogin函数里,这是两个层面的功能,在此处却被耦合在一个函数里。
{/* <button tag="login" id="button">点击打开登录浮层</button> */}
var showLogin = function(){
console.log( '打开登录浮层' );
log( this.getAttribute( 'tag' ) );
}
var log = function( tag ){
console.log( '上报标签为: ' + tag );
// (new Image).src = 'http:// xxx.com/report?tag=' + tag; // 真正的上报代码略
}
document.getElementById( 'button' ).onclick = showLogin;
// 使用 AOP分离之后,代码如下:
var showLogin = function(){
console.log( '打开登录浮层' );
}
var log = function(){
console.log( '上报标签为: ' + this.getAttribute( 'tag' ) );
}
showLogin = showLogin.after(log); // 打开登录浮层之后上报数据
document.getElementById('button').onclick = showLogin;
5.2:插件式的表单验证
<body>
用户名:<input id="username" type="text"/>
密码: <input id="password" type="password"/>
<input id="submitBtn" type="button" value="提交">
</body>
var username = document.getElementById( 'username' ),
password = document.getElementById( 'password' ),
submitBtn = document.getElementById( 'submitBtn' );
var formSubmit = function(){
if ( username.value === '' ){
return alert ( '用户名不能为空' );
}
if ( password.value === '' ){
return alert ( '密码不能为空' );
}
var param = {
username: username.value,
password: password.value
}
ajax( 'http:// xxx.com/login', param );
}
submitBtn.onclick = function(){
formSubmit();
}
Function.prototype.before = function( beforefn ){
var __self = this;
return function(){
if ( beforefn.apply( this, arguments ) === false ){
// beforefn 返回 false 的情况直接 return,不再执行后面的原函数 return;
}
return __self.apply( this, arguments );
}
}
var validata = function(){
if ( username.value === '' ){
alert ( '用户名不能为空' );
return false;
}
if ( password.value === '' ){
alert ( '密码不能为空' );
return false;
}
}
var formSubmit = function(){
var param = {
username: username.value,
password: password.value
}
ajax( 'http:// xxx.com/login', param );
}
formSubmit = formSubmit.before( validata );
submitBtn.onclick = function(){
formSubmit();
}
六:装饰者模式和代理模式
JavaScript设计模式(装饰者模式)的更多相关文章
- javascript设计模式——装饰者模式
前面的话 在程序开发中,许多时候都并不希望某个类天生就非常庞大,一次性包含许多职责.那么可以使用装饰者模式.装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象.本文将 ...
- 从ES6重新认识JavaScript设计模式: 装饰器模式
1 什么是装饰器模式 向一个现有的对象添加新的功能,同时又不改变其结构的设计模式被称为装饰器模式(Decorator Pattern),它是作为现有的类的一个包装(Wrapper). 可以将装饰器理解 ...
- JavaScript设计模式----装饰者模式
装饰者模式的定义: 装饰者(decorator)模式能够在不改变对象自身的基础上,在程序运行期间给对像动态的添加职责.与继承相比,装饰者是一种更轻便灵活的做法. 装饰者模式的特点: 可以动态的给某个对 ...
- 读书笔记之 - javascript 设计模式 - 装饰者模式
本章讨论的是一种为对象增添特性的技术,它并不使用创建新子类这种手段. 装饰者模式可以透明地把对象包装在具有同样接口的另一对象之中,这样一来,你可以给一些方法添加一些行为,然后将方法调用传递给原始对象. ...
- JavaScript设计模式—装饰器模式
装饰器模式介绍 为对象添加新的功能,不改变其原有的结构和功能,原有的功能还是可以使用,跟适配器模式不一样,适配器模式原有的已经不能使用了,装饰器示例比如手机壳 UML类图和代码示例 Circle示原来 ...
- JavaScript设计模式之----组合模式
javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...
- Java设计模式——装饰者模式
JAVA 设计模式 装饰者模式 用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式 ...
- JAVA设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- javascript的装饰者模式Decorator
刚开始看这段代码有点绕,现在回过头来看,so easy! Function.prototype.before = function(beforefn){ var _self = this; retur ...
- 从源码角度理解Java设计模式——装饰者模式
一.饰器者模式介绍 装饰者模式定义:在不改变原有对象的基础上附加功能,相比生成子类更灵活. 适用场景:动态的给一个对象添加或者撤销功能. 优点:可以不改变原有对象的情况下动态扩展功能,可以使扩展的多个 ...
随机推荐
- Netfilter 之 五个钩子点
概述 在协议栈的三层IPv4(IPv6还没看,不清楚)数据包的处理过程中,可能经过Netfilter的五个钩子点,分别为NF_INET_PRE_ROUTING.NF_INET_LOCAL_IN.NF_ ...
- windows下安装MongoDB服务
1,参考:https://www.cnblogs.com/lecaf/p/mongodb.html 2,要设置环境变量 3,设置用户 use admin 注:MongoDB安装好以后由默认的admi ...
- python——装饰器(不定长参数,闭包,装饰器)示例
def func(functionName): print("正在装饰") def func_in(*args, **kargs): print("------func_ ...
- MySQL5.7 创建及查看数据库
1.创建数据库语句create database语句是在MySQL实例上创建一个指定名称的数据库.create schema语句的语义和create database是一样的. 2.语法解析 CREA ...
- linux centos6.5 环境下安装redis的过程
过程还是挺折磨人的!谢谢许正同学一直耐心给我指导,虽然他也很忙.废话不多说: 首先,确保linux虚拟机联网: vm虚拟机>设置>Network Adapter 设置>网络配置设置成 ...
- java错误与异常
java异常处理机制 异常处理机制能让程序在异常发生时,按照代码的预先设定的异常处理逻辑,针对性地处理异常, 让程序尽最大可能恢复正常并继续执行,且保持代码的清晰.Java中的异常可以是函数中的语句执 ...
- JAVA 基础编程练习题9 【程序 9 求完数】
9 [程序 9 求完数] 题目:一个数如果恰好等于它的因子之和,这个数就称为"完数".例如 6=1+2+3.编程找出 1000 以内的 所有完数. package cskaoyan ...
- Django之权限(起步)
一. 权限概述 1. 认识权限 为什么要有权限? 因为权限让不同的用户拥有不同的功能. 权限可以对功能进行划分. 生活中处处有权限. 比如, 腾讯视频会员才有观看某个最新电影的权限, 你有房间钥匙就有 ...
- git-忽略不想提交到git的文件
在代码目录下建立.gitignore文件: .gitignore (用记事本另存可以保存这个名字),配置上要忽略的文件或者文件夹,然后提交到git 上就可以了.
- Docker Swarm常用命令
#查看集群节点 docker node ls #创建nginx服务 #docker pull hub.test.com:5000/almi/nginx:0.1 #下载私有仓库镜像 docker ser ...