javascript设计模式-----装饰者模式

一、装饰者模式

在装饰者模式中,可以在运行时动态添加附加功能到对象中,当处理静态类时,这可能是一个挑战。在javascript中,由于对象是可变的,因此,添加功能到对象中的过程本身并不是问题。

实现一:利用继承,来增强对象的功能

//装饰者模式 1
			function Sale(price){
				this.price = price || 100;
			}
			Sale.prototype.getPrice = function(){
				return this.price;
			}
			Sale.prototype.decorate = function(decorator){
				//临时构造函数,继承当前对象,装饰新对象
				var F = function(){},
					overrides = this.constructor.decorators[decorator],
					i,newobj;
				F.prototype = this;
				newobj = new F();
				//父类引用相当于__proto__
				newobj.father = F.prototype;
				for(i in overrides){
					if(overrides.hasOwnProperty(i)){
						newobj[i] = overrides[i];
					}
				}
				return newobj;
			}
			Sale.decorators = {};
			Sale.decorators.fedtax = {
				getPrice:function(){
					var price = this.father.getPrice();
					price += price * 5 / 100;
					return price;
				}
			};
			Sale.decorators.quebec = {
				getPrice:function(){
					var price = this.father.getPrice();
					price += price * 7.5 / 100;
					return price;
				}
			}
			Sale.decorators.money = {
				getPrice:function(){
					return "$" + this.father.getPrice().toFixed(2);
				}
			}
			Sale.decorators.cdn = {
				getPrice:function(){
					return "CDN$" + this.father.getPrice().toFixed(2);
				}
			}
			
			//测试 
			var sale = new Sale(100);
			sale = sale.decorate('fedtax');
			sale = sale.decorate('quebec');
			sale = sale.decorate('money');
			console.log(sale.getPrice());  //结果 $112.88
			
			sale = new Sale(100);
			sale = sale.decorate('fedtax');
			sale = sale.decorate('cdn');
			console.log(sale.getPrice());  //结果 CDN$ 105.00

1.装饰器都是静态对象,里面包含了要重载的方法。

2.调用子对象的方法,会先调用父对象的方法


实现二、使用装饰名称数组,不涉及继承

//装饰模式2
			function Sale(price){
				this.price = price || 100;
				this.decorators_list = []; 
			}
			Sale.prototype.decorate = function(decorator){
				this.decorators_list.push(decorator);
			}
			Sale.prototype.getPrice = function(){
				var price = this.price,
					i,
					max = this.decorators_list.length,
					name;
					for(i = 0;i<max;i++){
						name = this.decorators_list[i];
						price = Sale.decorators[name].getPrice(price);
					}
					return price;
			}
			Sale.decorators = {};
			Sale.decorators.fedtax = {
				getPrice:function(price){
					price += price * 5 / 100;
					return price;
				}
			};
			Sale.decorators.quebec = {
				getPrice:function(price){
					price += price * 7.5 / 100;
					return price;
				}
			}
			Sale.decorators.money = {
				getPrice:function(price){
					return "$" + price.toFixed(2);
				}
			}
			Sale.decorators.cdn = {
				getPrice:function(price){
					return "CDN$" + price.toFixed(2);
				}
			}
			
			//测试 
			var sale = new Sale(100);
			sale.decorate('fedtax');
			sale.decorate('quebec');
			sale.decorate('money');
			console.log(sale.getPrice());  //结果 $112.88
			
			sale = new Sale(100);
			sale.decorate('fedtax');
			sale.decorate('cdn');
			console.log(sale.getPrice());  //结果 CDN$ 105.00

此种方法利用了javascript本身的动态性,不需要用继承。简单的将前面的方法结果作为参数传递到下一个方法,而不是调用链中前面的方法。

这种实现方法可以很容易的支持反装饰或者撤销装饰,只需要简单的从装饰列表中删除项目即可。

缺点:该实现只有一个被装饰的方法,如果要装饰多个方法。修改列表数据结构为对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值