Android 源码中的外观模式

1,794 阅读4分钟

从装饰者模式到Context类族

当观察者模式和回调机制遇上Android源码

Android源码中的静态工厂方法

Android中的工厂方法模式

Android源码中的命令模式

Android源码中的适配器模式

定义

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

使用场景

  1. 当你要为一个复杂子系统提供一个简单接口时。
  2. 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
  3. 当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让他们仅通过Facade进行通讯,从而简化了他们之间的依赖关系。

结构

模式所涉及的角色有:

  • Client : 客户端程序。

  • Facade : 对外的统一入口,即外观对象。

  • SubSystem : 子系统或者子服务等等。

实现

编程嘛,抽象于生活高于生活,接下来我们用生活中智能家居的小例子来分析一下外观模式。智能家居为什么会流行,其中一个原因肯定是方便,我们用一个中央处理器就可以管理我们所有的智能家居产品,类似的还有现在的一站式服务那么用户就是Client角色,中央处理器就是Facade角色,音箱、TV、空调等等就是SubSystem角色。

Facade角色

public class Facade {

    private Light mLight = new Light();
    private AirCondition mAirCondition = new AirCondition();

    /**
     * 还可能会有方法集,比如我的习惯是下班回家,开灯、开空调,空调温度调节到20度
     */
    public void doMyHabit(){
        mLight.lightOn();
        mAirCondition.airConditionaOn();
        mAirCondition.setTemperature(20);
    }

    public void lightOn(){
        mLight.lightOn();
    }

    public void lightOff(){
        mLight.lightOff();
    }

    public void airConditionaOn() {
        mAirCondition.airConditionaOn();
    }

    public void airConditionaOff() {
        mAirCondition.airConditionaOff();
    }

    public void setTemperature(int temperature) {
        mAirCondition.setTemperature(temperature);
    }
}

子系统

public class Light {

    public void lightOn(){
        Log.e("Light","on");
    }

    public void lightOff(){
        Log.e("Light","off");
    }
}

public class AirCondition {

    public void airConditionaOn() {
        Log.e("AirCondition", "on");
    }

    public void airConditionaOff() {
        Log.e("AirCondition", "off");
    }

    public void setTemperature(int temperature) {
        Log.e("AirCondition", "temperature:" + temperature);
    }
}

不知道大家有没有发现一个问题,外观模式和我们上篇说的适配器模式是不是有一些相似呢?

Facade与Adapter和Proxy有类似之处,但是Proxy注重在为Client-Subject提供一个访问的中间层,Adapter注重对接口的转换与调整,而Facade所面对的往往是多个类或其他程序单元,通过重新组合各类及程序单元,对外提供统一的接口/界面。

在Android中,Context类族是比较重要的,关于这些,在从装饰者模式到Context类族,Android Handler 消息机制(解惑篇)中已经做过说明,这里就不再画UML图了。

它是提供应用环境(application environment)信息的接口。通过它可以访问到应用的资源和类,以及进行一些系统级别的操作,比如加载activity、发送广播和接收intent等。这代表什么呢,Context类给我们提供了一站式服务,这里当然应用了外观模式。

在应用启动时,首先会fork一个子进程,并且调用ActivityThread.main方法启动该进程。ActivityThread又会构建Application对象,然后和Activity、ContextImpl关联起来,然后再调用Activity的onCreate、onStart、onResume函数使Activity运行起来。

Activity启动之后,Android给我们提供了操作系统服务的统一入口,也就是Activity本身。这些工作并不是Activity自己实现的,而是将操作委托给Activity父类ContextThemeWrapper的mBase对象,这个对象的实现类就是ContextImpl ( 也就是performLaunchActivity方法中构建的ContextImpl )。

ContextImpl内部封装了一些系统级别的操作,有的子系统功能虽然没有实现,但是也提供了访问该子系统的接口,比如获取ActivityManager的getActivityManager方法。

外观模式非常的简单,只是封装了子系统的操作,并且暴露接口让用户使用,避免了用户需要与多个子系统进行交互,降低了系统的耦合度、复杂度。

测试代码已上传到github

参考链接

github.com/simple-andr…