一 定义
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式生成子类更加灵活。
二 使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能时
- 需要动态的给一个对象增加功能,这些功能可以再动态的撤销
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时
三 UML类图
- Component(抽象组件):接口或者抽象类,被装饰的最原始的对象。具体组件与抽象装饰角色的父类。
- ConcreteComponent(具体组件):实现抽象组件的接口。
- Decorator(抽象装饰角色):一般是抽象类,抽象组件的子类,同时持有一个被装饰者的引用,用来调用被装饰者的方法;同时可以给被装饰者增加新的职责。
- ConcreteDecorator(具体装饰类):抽象装饰角色的具体实现。
四 代码示例
4.1 创建抽象组件
public abstract class Component{
public abstract void operate();//装修方法
}
4.2 组件具体实现类
public class ConcreateComponent extends Component{
@Override
public void operate(){
//具体实现逻辑
}
}
4.3 抽象装饰类
public class Decorator extends Component{
private Component mComponent;
public Decorator(Component component){
this.mComponent = component
}
@Override
public void operate(){
//具体实现逻辑
mComponent.operte()
}
}
4.4 装饰者具体实现类
public class ConcreateDecoratorA extends Decorator {
public ConcreateDecoratorA (Component component){
super(component)
}
@Override
public void operate(){
//具体实现逻辑
operateA()
mComponent.operte()
operateB()
}
public void operateA(){
//装饰方法逻辑A
mComponent.operte()
}
public void operateB(){
//装饰方法逻辑B
mComponent.operte()
}
}
4.5 客户端调用
Component component = new ConcreateComponent()
ConcreateDecoratorA decorateA = new ConcreateDecoratorA (component)
decorateA.operate()
五 优点和缺点
优点:
- 采用组合的方式,可以动态的扩展功能,同时也可以在运行时选择不同的装饰器,来实现不同的功能。
- 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
- 被装饰者与装饰者解偶,被装饰者可以不知道装饰者的存在,同时新增功能时原有代码也无需改变,符合开放封闭原则
缺点:
- 装饰层过多的话,维护起来比较困难。
- 如果要修改抽象组件这个基类的话,后面的一些子类可能也需跟着修改,较容易出错。
六 Android源码中的应用
1.Activity、Service、Application和Context的联系
2.缓冲IO流就是对IO流的装饰
七 代理模式和装饰者模式的区别
7.1 区别
-
使用场景区别
代理模式侧重于对对象行为的特殊控制,不同的代理对象实现对被代理对象行为的不同的控制,并且这些代理的行为控制很少有组合的可能性。装饰者模式侧重于对被装饰对象属性的扩展,不同的装饰者对象会为被装饰者对象添加不同的属性,并且这些属性可以任意嵌套组合。
-
模式实现区别
装饰者模式需要提供装饰对象为参数的构造函数,而代理对象则无该项要求,主要原因是装饰者模式需要支持嵌套组合属性。(将装饰类传入另一个装饰类的构造器中,实现多重装饰的效果,避免了多继承)
7.2 联系
两者都是通过实现真实对象接口,并内置一个真实对象,通过操作该真实对象来实现接口