安卓设计模式(四)装饰者模式

本文将讨论Java设计模式中比较重要的模式之一:装饰者模式

该系列其他文章:

  • 安卓设计模式(一)面向对象六大设计原则
  • 安卓设计模式(二)单例模式
  • 安卓设计模式(三)Builder模式
  • 安卓设计模式(四)装饰者模式
  • 安卓设计模式(五)代理模式
  • 安卓设计模式(六)策略模式
  • 安卓设计模式(七)模板方法模式
  • 安卓设计模式(八)工厂方法模式

装饰者模式

装饰者模式也称为包装模式,属于结构型设计模式

定义:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活.

使用场景:需要透明且动态的地扩展类的功能时.

UML类图

安卓设计模式(四)装饰者模式_第1张图片

包括以下几个角色:

  • 抽象构件(Component)角色:给出一个抽象接口,规范待装饰者的功能方法。
  • 具体构件(ConcreteComponent)角色:待装饰类。
  • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
  • 具体装饰(ConcreteDecorator)角色:具体装饰者。

举例

Component:抽象组件

/**
 * =================中康================
 *
 * @Author: 陈振
 * @Email : [email protected]
 * @Time : 2016/11/1 14:36
 * @Action :待装饰者抽象:开发者
 *
 * =================中康================
 */
public abstract class Coder {
    public abstract void dev();//开发公司项目
}

ConcreteComponent:具体组件

/**
 * =================中康================
 *
 * @Author: 陈振
 * @Email : [email protected]
 * @Time : 2016/11/1 14:38
 * @Action :待装饰者具体实现:安卓开发一枚
 *
 * =================中康================
 */
public class AndroidCoder extends Coder {
    @Override
    public void dev() {
        Log.i("AndroidCoder", "开发公司的安卓项目");
    }
} 

Decorator:装饰者抽象

/**
 * =================中康================
 *
 * @Author: 陈振
 * @Email : [email protected]
 * @Time : 2016/11/1 14:42
* @Action :装饰者抽闲:具有维护开源项目的增强型功能
 *
 * =================中康================
 */
public abstract class OpenSource extends Coder {
    private Coder mCoder;

    public OpenSource(Coder coder) {//注意这里,装饰者会持有待装饰者组件的实例
        mCoder = coder;
    }

    public abstract void fixBug();//修复开源项目中的bug

    @Override
    protected void dev() {
        mCoder.dev();
    }
} 

ConcreteDecorator:具体装饰者

/**
 * =================中康================
 *
 * @Author: 陈振
 * @Email : [email protected]
 * @Time : 2016/11/1 14:44
 * @Action :装饰者,具有修复github上项目的bug的功能
 *
 * =================中康================
 */
public class GithubFixer extends OpenSource {
    public GithubFixer(Coder coder) {
        super(coder);
    }

    @Override
    public void fixBug() {
        Log.i("GithubFixer", "修复github上的bug");
    }

    @Override
    public void dev() {
        fixBug();//上班之前先看看开源项目有没有bug需要修复
        super.dev();//再开始开发
    }
} 

实际使用

    AndroidCoder androidCoder = new AndroidCoder();//安卓开发者

    androidCoder.dev();//以前每天上班就是写代码

    //装饰者模式之后
    GithubFixer githubFixer = new GithubFixer(androidCoder);//公司项目没那么紧,每天开发之前可以先维护下开源项目
    githubFixer.dev();

    new GithubFixer(androidCoder).dev();//与以上等价

结果:

AndroidCoder: 修复github上的bug
GithubFixer:开发公司的安卓项目

分析

在这个例子中,安卓程序猿一天的工作就是开发公司的项目,即androidCoder.dev(),后来想要增强自己的功能,需要维护github上的开源项目,于是便使用了GithubFixer来装饰自己,即:new GithubFixer(androidCoder).dev(),这样在每次每天开发之前都会去先维护开源项目,再去开发.

  1. 对于调用者,这完全是透明的,在所有基础调用的位置,做以下替换就可以:

     androidCoder.dev();//==>
    
     new GithubFixer(androidCoder).dev();
     //当然也可以维护更多社区的项目...
     new OsChinaFixer(androidCoder).dev();
    
  2. 另外,GithubFixer不仅仅可以装饰androidCoder,IosCoder-JavaCoder等等都可以装饰,例如:

     new GithubFixer(iosCoder).dev();
     new GithubFixer(phpCoder).dev();
    
  3. 如果你使用继承来为AndroidCoder(ios-php等等)增加fixBug功能,组件类别比较多的情况下,势必会造成体系的臃肿,但是反观装饰者模式,由于是动态的为组价增强功能,则很好的避免了继承体系臃肿的问题.

  4. 装饰者模式可以链式调用,例如:

     new PlayGame(new GithubFixer(iosCoder)).dev;//为组件增加维护开源项目,打游戏的功能
    
  5. 组件的原有功能没有任何破坏,Coder.dev()保持内部逻辑;

  6. 装饰者内部会持有待装饰者组件实例

Android源码中装饰者模式的使用

在源码中装饰者模式被使用的地方还是很多的,最典型的是Context体系,这里简单分析一下:

  • Context - 抽象组件
  • ContextImpl - 具体组件:继承自Context,实现了Context中的抽象方法;
  • ContextWrapper - 装饰者抽象:继承Context,定义了一些增强方法,内部持有Context引用
  • ContextThemeWrapper - 具体装饰者父类:实现了ContextWrapper中的抽象方法,提供一些通用实现
  • Activity,Service,Application - 具体装饰者实现类:实现全部的装饰方法

关于作者

你可能感兴趣的:(安卓设计模式(四)装饰者模式)