设计模式——装饰模式

装饰模式

定义

装饰者模式又称为包装(wrapper)模式。装饰者模式对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

模板

抽象构件(Component)角色:给出一个抽象接口,以规范准备接受附加责任的对象。
 具体构件(ConCreteComponent)角色:定义一个将要接受附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
 具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

装饰模式模板

实例

a) 客户端埋点:经常将回调接口再包装一层,在包装层完成埋点或者其它非主功能的辅助代码
例: 对下载回调listener包装一层,进行下载的埋点。

b) 添加额外的辅助功能: 某个异步回调接口,可能出现回调收不到的bug,这时想设计一种 带自动超时功能的回调:
// 原listener

public interface IListener<T> {
    void onSuccess(T result);
    void onError(String errorCode, String errorDesc);
}

// 带自动超时功能的listener

public class AutoTimeoutResultListener<T> extends AbstractAutoTimeout
        implements IListener<T> {

    private IListener<T> mListener;

    public AutoTimeoutResultListener(IListener<T> listener) {
        mListener = listener;
    }

    @Override
    public synchronized void onSuccess(T result) {
        mListener.onSuccess(result);
    }

    @Override
    public synchronized void onError(String errorCode, String errorDesc) {
       mListener.onError(errorCode, errorDesc);
    }

    @Override
    synchronized void onTimeout() {
        mListener.onError(Constants.ERROR_CODE_TIME_OUT, "IListener time out.");
    }
}

装饰模式的简化:
(1) 只有一个ConcreteComponent时,可以考虑去掉抽象的Component类,把Decorator作为ConcreteComponent的子类。
(2) 如果只有一个ConcreteDecorator类,可以将Decorator类和ConcreteDecorator的责任合成一个类。

透明性要求:
装饰模式对客户端的透明性要求程序不要声明Decorator类型的变量,而应该声明Component接口变量。

半透明的装饰模式:
纯粹的装饰模式已经很难找到了,装饰模式的用意是在不改变接口的前提下,增强类的性能。在增强性能时,需要建立新的方法,但是纯粹的装饰模式无法通过Component调用新建立的方法,这时候需要破坏透明性,才能使用新方法。

半透明的装饰模式是介于装饰模式和适配器模式之间的,装饰模式和适配器模式都是“包装模式”,它们都通过封装其他的对象达到设计的目的,但是邢台有很大区别。

理想的装饰模是在被装饰对象进行功能增强时,要求具体的构件角色、装饰角色的接口和抽象构件角色的接口完全一致。而适配器并不要求对原对象进行增强,但会改变对象的接口,以便和目标接口相符合。

透明性

优点

  1. 对原有代码的侵入性很小,可以在不改变原有代码结构的同时增加新的功能,如遇到紧急上线等情况不失为一种好的解决方法。
  2. 可以在装饰类中增加新的功能/增强原有的功能,也符合职责单一原则,装饰类专门做某种处理(埋点/超时处理)

缺点

  1. 增加新的类
  2. 多层装饰比较复杂,影响代码的维护及可读性

适用场景

  1. 需求开发紧急,添加新功能
  2. 普通的添加新功能也可以使用该种方法

其它实例:

原文地址:https://www.cnblogs.com/NeilZhang/p/11885429.html