Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Android 设计模式情景分析——装饰模式

$
0
0

转载请注明出处:http://blog.csdn.net/smartbetter/article/details/70834042

在现实生活中,人需要各式各样的衣物,不管你穿着怎样,但是,对于个人的本质来说是不变的,充其量只是在外面披上一层遮盖物而已,这就是装饰模式,装饰模式也称为包装模式,结构型设计模式之一,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一,动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比于生成子类更为灵活。

1.装饰模式的使用情景

需要透明且动态地扩展类的功能时。

2.装饰模式的UML类图

装饰模式的UML类图

3.装饰模式的通用模式代码

1.抽象组件 Component:

public interface Component {
    void operate();
}

2.组件具体实现类 ConcreteComponent:

public class ConcreteComponent implements Component {
    @Override
    public void operate() {
        // 具体逻辑
    }
}

3.抽象装饰类 Decorator,职责就是为了装饰我们的组件对象,内部一定要有一个指向组件对象的引用:

public abstract class Decorator implements Component {
    private Component component;
    // 必须的构造方法
    public Decorator(Component component) {
        this.component = component;
    }
    public void operate() {
        component.operate();
    }
}

4.装饰者的具体实现类 ConcreteDecoratorA、ConcreteDecoratorB(ConcreteDecoratorB 的代码和 ConcreteDecoratorA 本质无区别,只是实现不同,这里不再给出):

public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    public void operate() {
        operateA();
        super.operate();
        operateB();
    }
    // 自定义的装饰方法
    public void operateA() {
        // 装饰方法逻辑
    }
    // 自定义的装饰方法
    public void operateB() {
        // 装饰方法逻辑
    }
}

5.编写测试类:

@Test
public void test() throws Exception {
    // 构造被装饰的组件对象
    Component component = new ConcreteComponent();
    // 根据组件对象构造装饰者对象A并调用,此时相当于给组件对象增加装饰者A的功能方法
    Decorator decoratorA = new ConcreteDecoratorA(component);
    decoratorA.operate();
    Decorator decoratorB = new ConcreteDecoratorB(component);
    decoratorB.operate();
}

4.Android系统源代码中的应用情景

Android系统源代码中的装饰模式也是常接触的,例如“上帝对象” Context 在我们装饰模式里就相当于抽象组件,而在其内部定义了大量的抽象方法,比如经常用到的 startActivity() 方法:

public abstract class Context {
    // 省略代码
    public abstract void startActivity(@RequiresPermission Intent intent);
    public abstract void startActivity(@RequiresPermission Intent intent, @Nullable Bundle options);
    // 省略代码
}

而其真正的实现是在 ContextImpl(Framework层) 中完成的:

class ContextImpl extends Context {
    // 省略代码
    @Override
    public void startActivity(Intent intent) {
        warnIfCallingFromSystemProcess();
        startActivity(intent, null);
    }
    @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
    // 省略代码
}

这里 ContextImpl 就相当于组件具体实现类,其次我们知道,Activity 从类层次上来说本质是一个 Context,Activity 也并非直接 继承于 Context,而是继承于 ContextThemeWrapper:

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
    // 代码省略
}

而 ContextThemeWrapper 又继承于 ContextWrapper,ContextWrapper 才继承于 Context,为什么层次这么复杂呢?其实这里就是一个典型的装饰模式,ContextWrapper 就是装饰者,在 ContextWrapper 中有一个 Context 的引用:

public class ContextWrapper extends Context {
    Context mBase;
    public ContextWrapper(Context base) {
        mBase = base;
    }
    // 代码省略
    @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }
    @Override
    public void startActivity(Intent intent, Bundle options) {
        mBase.startActivity(intent, options);
    }
    // 代码省略
}

到这里已经可以看出装饰模式的模样了。

作者:smartbetter 发表于2017/4/27 14:08:46 原文链接
阅读:185 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>