JavaScript学习笔记(四十四) 装饰器
装饰器模式(Decorator)
用法(Usage)
var sale = new Sale(100); // the price is 100 dollars
sale = sale.decorate('fedtax'); // add federal tax
sale = sale.decorate('quebec'); // add provincial tax
sale = sale.decorate('money'); // format like money
sale.getPrice(); // "$112.88"
在其它场景中,购买者可能在一个没有省税的省,并且你也可能想用加币(Canadian dollars)格式化价格,那么你可以这样做:
var sale = new Sale(100); // the price is 100 dollars
sale = sale.decorate('fedtax'); // add federal tax
sale = sale.decorate('cdn'); // format using CDN
sale.getPrice(); // "CDN$ 105.00"
正如你看到的,这是一种在运行时灵活添加功能和调整对象的方法。让我们看一下如何实现这种模式。
实现(Implementation)
实现装饰器模式的一个方法是每个装饰器都是一个对象包含了应该被重写的方法。实际上每个装饰器都继承至前一个装饰器装饰之后的增强对象。每个被装饰的方法将调用在uber(继承的对象)上相同的方法且获取值并额外做一些处理。
function Sale(price) {
this.price = price || 100;
}
Sale.prototype.getPrice = function() {
return this.price;
};
所有将被实现的装饰器对象将被作为构造方法属性的属性:
Sale.decorators = {};
让我们看一个装饰器的例子。它是一个实现了自定义的getPrice()方法的对象。记住这个方法首先从parent方法获得值然后修改那个值:
Sale.decorators.fedtax = {
getPrice: function() {
var price = this.uber.getPrice();
price += price * 5 / 100;
return price;
}
};
类似的我们可以实现其它的装饰器,需要多少实现多少。它们可以作为核心Sale()的功能扩展,像插件一样实现(implemented like plugins)。它们甚至可以“存活”在额外的文件中,可以被第三方开发者开发和共享:
Sale.decorators.quebec = {
getPrice: function() {
var price = this.uber.getPrice();
price += price * 7.5 / 100;
return price;
}
};
Sale.decorators.money = {
getPrice: function() {
return "$" + this.uber.getPrice().toFixed(2);
}
};
Sale.decorators.cdn = {
getPrice: function() {
return "CDN$ " + this.uber.getPrice().toFixed(2);
}
};
最后让我们看一下“神奇(magic)”的decorate()方法,它将所有部分都连接在一起。
sale = sale.decorate('fedtax');
这个"fedtax"字符串将相当于Sale.decorators.fedtax实现的对象。新的被装饰的对象newobj将会继承我们现有的对象(最初的对象,或在上一个装饰器添加之后的对象),就是this对象。为了做到继承这部分,让我们使用前面提到过的临时构造函数模式。我们也设置newobj的uber属性,所以child可以访问到parent。然后从装饰器复制所有的其它属性到新的被装饰的对象newobj。最后newobj被返回,在我们的示例中,它将会成为新的被更新的sale对象:
Sale.prototype.decorate = function(decorator) {
var F = function() {},
overrides = this.constructor.decorators[decorator],
i,
newobj;
F.prototype = this;
newobj = new F();
newobj.uber = F.prototype;
for (i in overrides) {
if (overrides.hasOwnProperty(i)) {
newobj[i] = overrides[i];
}
}
return newobj;
};
JavaScript学习笔记(四十四) 装饰器的更多相关文章
- JavaScript学习笔记(十四)——对象
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
- Python学习笔记(十四)
Python学习笔记(十四): Json and Pickle模块 shelve模块 1. Json and Pickle模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不 ...
- VSTO学习笔记(十四)Excel数据透视表与PowerPivot
原文:VSTO学习笔记(十四)Excel数据透视表与PowerPivot 近期公司内部在做一种通用查询报表,方便人力资源分析.统计数据.由于之前公司系统中有一个类似的查询使用Excel数据透视表完成的 ...
- python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法
python3.4学习笔记(二十四) Python pycharm window安装redis MySQL-python相关方法window安装redis,下载Redis的压缩包https://git ...
- 如鹏网学习笔记(十四)ASP.NET
Asp.net笔记 一.Socket类 进行网络编程的类,可以在两台计算机之间进行网络通讯 过程: 向服务器发送指令: GET /index.html HTTP/1.1 Host:127.0.0.1: ...
- 《机器学习实战》学习笔记第十四章 —— 利用SVD简化数据
相关博客: 吴恩达机器学习笔记(八) —— 降维与主成分分析法(PCA) <机器学习实战>学习笔记第十三章 —— 利用PCA来简化数据 奇异值分解(SVD)原理与在降维中的应用 机器学习( ...
- (C/C++学习笔记) 二十四. 知识补充
二十四. 知识补充 ● 子类调用父类构造函数 ※ 为什么子类要调用父类的构造函数? 因为子类继承父类,会继承到父类中的数据,所以子类在进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程. ...
- Android学习笔记(十四)——自定义广播
//此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 我们除了可以通过广播接收器来接收系统广播, 还可以在应用程序中发送自定义的广播.下面我们来分别试一试发送自定义 ...
- Dynamic CRM 2013学习笔记(十四)复制/克隆记录
经常有这样的需求,一个单据上有太多要填写的内容,有时还关联多个子单据,客户不想一个一个地填写,他们想从已有的单据上复制数据,克隆成一条新的记录.本文将介绍如何克隆一条记录,包括它的子单据以生成一条新的 ...
- Java框架spring 学习笔记(十四):注解aop操作
回见Java框架spring Boot学习笔记(十三):aop实例操作,这里介绍注解aop操作 首先编写一个切入点HelloWorld.java package com.example.spring; ...
随机推荐
- linux使用技巧(shell/vi/screen)
1,Shell bash > awk '{print {NF}}' file 此时想修改操作命令可参照下面快捷方式 ctrl a 光标移动到命令最前面 ctrl e 光标移动到命令最后面 ctr ...
- Ubuntu 12.10 安装JDK7
1.首先到oracle下载上下载jdk-7u25-linux-i586.tar.gz 2.将jdk-7u25-linux-i586.tar.gz复制到/usr/lib/jvm/目录以下,这里假设没有j ...
- CodeForces 448
A:Rewards: 题目链接:http://codeforces.com/problemset/problem/448/A 题意:Bizon有a1个一等奖奖杯,a2个二等奖奖杯,a3个三等奖奖杯,b ...
- 如何让HTML的编写更具结构性
首先声明,我不是搞技术的,很多词汇写的不够专业,但作为一枚菜鸟,我站在菜鸟的角度,来讲述我在学习技术的过程中所遇到的问题,和解决的方案. 入门HTML还算简单,无非是先写好固定的三对开闭标签结构:ht ...
- Enze Second day
哈喽,很高兴在云和学院又学了一天的新知识,现在,我来继续总结一下今天所学的以及对昨天的一些补充. 变量 • 声明变量的语法格式: –数据类型 变量名; •赋值: 变量名=值; 变量的命名 • ...
- Spring源码地址和相关介绍的网址
Spring源码地址下载: https://github.com/spring-projects/spring-framework/tags >多图详解Spring框架的设计理念与设计模式:ht ...
- codeforces 464B Restore Cube
题目链接 给8个点, 判断这8个点能否组成一个正方体, 如果能, 输出这8个点. 同一个点的x, y, z可以交换. 每一个点有6种排列方式, 一个8个点, 暴力枚举出所有排列方式然后判断能否组成正方 ...
- design pattern factory method #Reprinted#
引入人.工厂.和斧子的问题: (1),原始社会时,劳动社会基本没有分工,需要斧子的人(调用者)只好自己去磨一把斧子,每个人拥有自己的斧子,如果把大家的石斧改为铁斧,需要每个人都要学会磨铁斧的本领,工作 ...
- Code one 码
Code one是一种用成像设备识别的矩阵式二维条码.Code one符号中包含可由快速性线性探测器识别的识别图案.每一模块的宽和高的尺寸为X. Code one符号共有10种版本及时14种尺寸.最 ...
- hibernate HQL查询 2.2
hql(都要在事务中完成)session.beginTransaction();session.getTransaction().commit(); session.beginTransaction( ...