定义
在不改变原有对象的基础上,将功能附加到对象上(提供了比继承更有弹性的替代方案,属于结构型模式)
先来看结构图:
装饰器四个角色:
- Component(被装饰对象基类):定义对象的接口,可以给这些对象动态增加职责。
- ConcreteComponent(具体被装饰对象):定义具体的对象,Decorator可以给它增加额外的职责。
- Decorator(装饰器抽象类):维护指向Component实例的引用,定义与Component一致的接口(也就是要继承或实现的被装饰对象基类),具体装饰由其子类实现。
- ConcreteDecorator(具体装饰者):具体的装饰对象,Decorator的子类,给内部持有的具体被装饰对象增加具体职责。
其实代码逻辑十分简单,直接来情景模拟比较好理解:
现在酒店有服务员,服务员只会机械的在服务,为了提升业绩,要求每个服务员要微笑地服务。使用装饰器模式来实现此情景。
服务员的父接口Service,里面有service()方法
package com.zlfan.decorator;
/*
* 相当于Component接口
*/
public interface Service {
void service();
}
服务员
package com.zlfan.decorator;
/*
* 相当于ConcreteComponent
*/
public class Waiter implements Service {
@Override
public void service() {
System.out.println("在服务...");
}
}
接下来是装饰器模式的核心,内部维护了服务员,要被装饰的方法
package com.zlfan.decorator;
/*
* 装饰抽象类,实现了Component,从外类来扩展Component类的功能,
* 但对于Component来说,是无需知道Decorator存在的。
*/
public abstract class WaiterDecorator implements Service {
Service service;
public WaiterDecorator(Service service){
this.service = service;
}
@Override
public void service() {
service.service();
}
}
接下来我们就可以通过继承上面的WaiterDecorator类来装饰service()方法了
package com.zlfan.decorator;
/*
* 额外给服务员添加微笑 相当于ConcreteDecorator
*/
public class SmileWaiter extends WaiterDecorator{
public SmileWaiter(Service service) {
super(service);
}
@Override
public void service() {
System.out.println("装饰:微笑");
super.service();
}
}
注意上面的service()方法中,我给他增加了 微笑 ,然后才调用了内部维护的服务员的service()。也就是给他增加了额外的功能
测试类
package com.zlfan.decorator;
public class Test {
public static void main(String[] args) {
Service sv = new Waiter();
sv.service();
System.out.println("-----装饰后------");
Service svm = new SmileWaiter(new Waiter());
svm.service();
}
}
运行结果
在服务...
-----装饰后------
装饰:微笑
在服务...
装饰器模式的使用场景
在不影响其他对象的情况下,以动态的、透明的方式给单个对象添加职责。
- 处理那些可以撤销的职责。
- 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量子类,使子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类。
优缺点
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,可以动态扩展一个实现类的功能。符合开闭原则。
缺点:多层装饰比较复杂。