概念
动态地将行为附加到对象上。提供了比继承更具有弹性的替代方案
所谓”动态”,是指在运行时根据具体的需求添加行为,相对的,”静态”则是在编译时就确定了具体的行为,两者的区别很明显,动态添加行为具有很好的可扩展性,不需要修改已有的代码,这对于维护更新是很有利的。
设计原则
类应该对扩展开放,对修改关闭
对原有代码修改的代价是很大的,很可能引入未知的 bug 和意外的副作用,所以要对修改关闭,而使用扩展来应对改变的需求,在不修改原有代码的情况下就能添加新行为。多用组合,少用继承
如同策略模式,使用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为,而如果使用组合来扩展对象的行为,就可以在运行时动态的添加行为。
理解
在装饰者模式中,存在两个角色:组件(Component) 和 装饰器(Decorator),并且两者要实现相同的接口或抽象类(实现接口或继承抽象类都行),这样就可以使用装饰器来装饰组件了。现实生活中有很多这样的例子,比如购买手机时,一个裸机就算是一个组件,如果想要装饰下手机,加个手机套,贴个膜,送支手写笔等,这些就是装饰器。通过装饰,在原有对象的基础上得到了一个新的具有更多属性和行为的对象,比如加了手机套的手机比裸机耐摔,这便是装饰后得到的新属性;有了手写笔的手机可以有新的输入方式,这便是装饰后得到的新行为。
实例
现实生活中有很多事物可以描述装饰者模式,就拿上面提到的手机配件的例子来写一个模拟代码
在这个例子中,有一个抽象类 Phones,作为组件和装饰器的共同基类;有两个组件,AndroidPhone 和 iOSPhone,装饰器数量不确定,因此有个装饰器基类 PhoneAccessory,然后派生出一些可选的装饰器,比如 手机壳:PhoneCover,手机膜:PhoneMembrane,手写笔:PhonePen。他们之间的关系可以用如下类图描述
通过类图可以很清楚的看到装饰者模式的思路,下面是具体代码:
抽象基类
public abstract class Phones {
String description="nothing";
public String getDescription(){
return description;
}
}
Android 手机
public class AndroidPhone extends Phones {
public AndroidPhone(){
description="Android 手机";
}
}
iOS 手机
public class iOSPhone extends Phones {
public iOSPhone(){
description="iOS 手机";
}
}
装饰器基类
public abstract class PhoneAccessory extends Phones {
public abstract String getDescription();
}
手机壳装饰器
public class PhoneCover extends PhoneAccessory{
private Phones phone;
public PhoneCover(Phones p){
this.phone=p;
}
@Override
public String getDescription() {
return this.phone.getDescription()+" 加了个保护套";
}
}
手机膜装饰器
public class PhoneMembrane extends PhoneAccessory {
private Phones phones;
public PhoneMembrane(Phones p){
this.phones=p;
}
@Override
public String getDescription() {
return this.phones.getDescription()+" 贴了个膜";
}
}
手写笔装饰器
public class PhonePen extends PhoneAccessory{
private Phones phone;
public PhonePen(Phones p){
this.phone=p;
}
@Override
public String getDescription() {
return this.phone.getDescription()+" 送了支手写笔";
}
}
测试
public class MainTest {
public static void main(String[] args) {
Phones phone = new AndroidPhone();
System.out.println(phone.getDescription());
PhoneCover coverPhone = new PhoneCover(phone);
System.out.println(coverPhone.getDescription());
PhoneMembrane membranePhone = new PhoneMembrane(coverPhone);
System.out.println(membranePhone.getDescription());
PhonePen penPhone = new PhonePen(membranePhone);
System.out.println(penPhone.getDescription());
}
}
运行结果: