装饰者模式提供了对一个对象动态添加额外临时的功能职责(属性和方法)。注意的是装饰者添加的功能,对于原本的对象来说并不是必要的,否则,该功能应该添加到对象原型中。 装饰者模式一般用于修改现有系统,希望为对象添加额外功能,而不需要修改体层代码。 一些类库例如JQuery,也有使用类似模式。jQuery.extend()方法就是用来扩展jQuery内置对象,可以认为是装饰者模式一种实现。
var User = function(name) {
this.name = name;
this.say = function() {
log.add("User: " + this.name);
};
}
var DecoratedUser = function(user, street, city) {
this.user = user;
this.street = street;
this.city = city;
this.say = function() {
log.add("Decorated User: " + this.user.name + ", " +
this.street + ", " + this.city);
};
return this;
}
// logging helper
var log = (function() {
var log = "";
return {
add: function(msg) { log += msg + "\n"; },
show: function() { console.log(log); log = ""; }
}
})();
function run() {
var user = new User("Kelly");
user.say(); //User: Kelly
var decorated = new DecoratedUser(user, "Broadway", "New York");
decorated.say(); //Decorated User: Kelly, Broadway, New York
log.show();
}
run();
优点: 1. 相当灵活,旧的代码如果需要添加新的行为,可以在上面进行包装或者“装饰”,不用修改原来的底层代码 1. 不必依靠大量子类实现一些功能 缺点: 1. 如果滥用,会极大复杂化程序框架,解决方法应使用大量注解和文档说明,同时要限制装饰者数量
抽象装饰者(Abstract Decorator)模式
class User {
constructor(name){
this.name = name;
this.classType = 'normal';
}
say(){
log.add("User: " + this.name+ "; classType:" + this.classType);
}
}
class UserVip extends User {
constructor(name){
super(name);
this.classType = 'VIP';
}
}
class UserDecorator {
constructor(user,street){
this.user = user;
this.street = street;
}
getStreet(){
return " Decorated User Street is: "+this.street
}
say(){
const user = this.user;
log.add("User: " + user.name+ "; classType:" + user.classType + this.getStreet());
}
}
class CaseUserDecorator extends UserDecorator{
constructor(user, street, city){
super(user, street);
this.city = city;
}
getCity(){
return " caseDecorated User City is: "+this.city
}
say(){
const user = this.user;
log.add("User: " + user.name+ "; classType:" + user.classType + this.getStreet() + '; ' + this.getCity());
}
}
// logging helper
var log = (function() {
var log = "";
return {
add: function(msg) { log += msg + "\n"; },
show: function() { console.log(log); log = ""; }
}
})();
function run() {
var user = new User("Mike");
user.say(); //User: Mike; classType:normal
var decoratedUser = new UserDecorator(user, "Broadway");
decoratedUser.say(); // User: Mike; classType:normal Decorated User Street is: Broadway
var userVip = new UserVip("Kelly");
userVip.say(); //User: Kelly; classType:VIP
var decoratedVipUser = new CaseUserDecorator(userVip, "Broadway", "New York");
decoratedVipUser.say(); // User: Kelly; classType:VIP Decorated User Street is: Broadway; caseDecorated User City is: New York
log.show();
}
run();