Android 设计模式-外观模式

1.外观模式

外观模式Facade Pattern,也叫门面模式、Facade模式。属于结构型设计模式之一。

外观模式要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。外观模式提供一个统一的高层次的接口,使得子系统更容易使用。

一般第三方SDK经常使用外观模式,通过一个外观类使得整个系统的接口只有一个统一的高层接口,降低用户的使用成本,也对用用户屏蔽很多实现细节。

使用场景:

①为一个复杂的子系统提供一个简单接口,对外隐藏子系统的具体实现、隔离变化;

②当需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点。如果子系统间是相互依赖的,就可以让它们仅通过Facade接口进行通信,从而简化它们之间的依赖关系。

UML类图:

bdbb1f4adfc944b7b4d2739f8336af10.webp

 Facade:系统对外的统一接口,客户端连接子系统功能的入口。

SubSystem子系统:可以同时有一个或多个子系统,每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。

外观模式是一个高频率使用的设计模式,它的精髓在于封装二字。通过一个高层次结构为用户提供统一的API入口,使得用户通过一个类型就基本能够操作整个系统,从而减少了用户的使用成本,也能够提升系统的灵活性。

优点:

①对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化。

②外观类对子系统的接口封装,使得系统更易于使用。

③使用外观模式可以将一个子系统和使用它的客户端自己其他子系统分离开来,这样就提高了子系统的独立性和可移植性。

缺点:

①外观类接口复杂。由于子系统的接口都有外观类统一对外暴露,使得外观类的API接口较多,在一定程度上增加了用户使用成本。

②增加新的子系统可能需要修改外观类的源代码,违背了开闭原则。

2.外观模式理解

先通过一个简单的例子来了解外观模式。其实手机可以看作是一个外观类,而手机中的功能,比如打电话、相机则是各种子模块。

①打电话的功能

//电话功能接口

public interface Phone {

    public void dail();//打电话

    public void hangup();//挂断

}

//电话的实现类

public class PhoneImpl implements Phone {

    @Override

    public void dail() {

        System.out.println("打电话");

    }

    @Override

    public void hangup() {

        System.out.println("挂断");

    }

}

②相机的功能

//相机功能接口

public interface Camera {

    public void open();//打开相机

    public void takePhoto();//拍照

    public void close();  //关闭相机

}

//相机功能的实现类

public class MiCamera implements Camera {

    @Override

    public void open() {

        System.out.println("打开相机");

    }

    @Override

    public void takePhoto() {

        System.out.println("拍照");

    }

    @Override

    public void close() {

        System.out.println("关闭相机");

    }

}

③手机

public class MobilePhone {

    private Phone mPhone = new PhoneImpl();

    private Camera mCamera = new MiCamera();

    //拍照

    public void takePhoto() {

        mCamera.open();

        mCamera.takePhoto();

        mCamera.close();

    }

    //视频聊天

    public void videoChat() {

        mCamera.open();

        mPhone.dail();

    }

}

我们使用手机时,需要用到拍照和视频聊天的功能,但我们不需要知道相机的信息,也不需要知道视频聊天要用到了哪些类、Phone的接口和实现等,只需要用到手机MobilePhone这个类和它提供的接口takePhoto和videoChat:

MobilePhone mobilePhone = new MobilePhone();

mobilePhone.takePhoto();

mobilePhone.videoChat();

3.外观模式的应用

开发过程中,ImageLoader就使用了外观模式。

外观类ImageLoader,所有的功能都通过调用ImageLoader类来实现:

public class ImageLoader {

    ImageLoaderConfig mConfig;//图片加载配置

    ImageCache mImageCache = new MemoryCache();// 图片缓存,依赖接口

    private RequestQueue requestQueue;//请求队列

    private static ImageLoader mImageLoader = null;

    private ImageLoader () {}

    public static ImageLoader getInstance() {

        //省略单例实现

    }

    public void init(ImageLoaderConfig config) {

        mConfig = config;

        mImageCache = config.mImageCache;

        checkConfig();

        requestQueue = new RequestQueue( config.threadCount);

        requestQueue.start();

    }

    private void checkConfig() {

        //省略部分代码

    }

    public ImageLoaderConfig getConfig() {

        return mConfig;

    }

    public void displayImage(final ImageView imageView, String url) {

        displayImage(imageView, url, null);

    }

    public void displayImage(final ImageView imageView, String url, DisplayConfig config) {

        ImageRequest request = new ImageRequest(imageView, url, config);

        request.displayConfig = request.displayConfig != null ? request.displayConfig : mConfig.displayConfig;

        requestQueue.addRequest(request);

    }

}

ImageLoader类里面封装了配置类ImageLoaderConfig和请求队列RequestQueue。请求队列RequestQueue里面又封装了线程模型等。调用ImageLoader的init方法以后,用户就可以直接用display方法来加载显示图片了,而不用管网络请求、队列这些细节,所有的实现细节都被封装在ImageLoader类下面,用户只需要操作ImageLoader的接口就可以完成图片的加载操作,这样就避免暴露了过多的实现细节,而且用户使用起来也更加简单。

注:Android源码中,Context就是外观模式的一个例子。Context这个抽象类定义了很多我们熟知的方法,它的具体实现都在ContextImpl.java这个类里。

猜你喜欢

转载自blog.csdn.net/zenmela2011/article/details/126156513