码迷,mamicode.com
首页 > 移动开发 > 详细

java/android 设计模式学习笔记(14)---外观模式

时间:2016-07-17 23:51:46      阅读:489      评论:0      收藏:0      [点我收藏+]

标签:

  这篇博客来介绍外观模式(Facade Pattern),外观模式也称为门面模式,它在开发过程中运用频率非常高,尤其是第三方 SDK 基本很大概率都会使用外观模式。通过一个外观类使得整个子系统只有一个统一的高层的接口,这样能够降低用户的使用成本,也对用户屏蔽了很多实现细节。当然,在我们的开发过程中,外观模式也是我们封装 API 的常用手段,例如网络模块、ImageLoader 模块等。其实我们在开发过程中可能已经使用过很多次外观模式,只是没有从理论层面去了解它。
  转载请注明出处:http://blog.csdn.net/self_study/article/details/51931196
  PS:对技术感兴趣的同鞋加群544645972一起交流。

设计模式总目录

  java/android 设计模式学习笔记目录

特点

  外观模式提供一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。
  外观模式的使用场景:

  • 为一个复杂子系统提供一个简单接口。Facade 可以提供一个简单统一的接口,对外隐藏子系统的具体实现、隔离变化。
  • 当需要构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点。如果子系统之间是相互依赖,你可以让他们仅通过 Facade 接口进行通信,从而简化了它们之间的依赖关系。
  外观模式简化了接口,并且同时允许我们让客户端和子系统之间避免紧耦合。

UML类图

  外观模式没有一个一般化的类图描述,我们先用一个结构图来说明:
  技术分享
根据结构图抽象出一个类图:
技术分享
外观模式有两个角色:

  • Facade 角色:系统对外的统一接口,客户端连接子系统功能的入口。
  • 子系统角色(SubSystem)角色:可以同时有一个或者多个子系统,每个子系统都不是一个单独的类,而是一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并不知道门面的存在,对于子系统而言,门面仅仅是另外一个客户端而已。
我们根据上面的 uml 类图可以写出外观模式的通用代码:
子系统:

public class SystemA {

    public void operation1(){
        System.out.print("SystemA:operation1\n");
    }

    public void operation2(){
        System.out.print("SystemA:operation2\n");
    }

    public void operation3(){
        System.out.print("SystemA:operation3\n");
    }
}
public class SystemB {

    public void operation1(){
        System.out.print("SystemB:operation1\n");
    }

    public void operation2(){
        System.out.print("SystemB:operation2\n");
    }

    public void operation3(){
        System.out.print("SystemB:operation3\n");
    }
}
public class SystemC {
    public void operation1(){
        System.out.print("SystemC:operation1\n");
    }

    public void operation2(){
        System.out.print("SystemC:operation2\n");
    }

    public void operation3(){
        System.out.print("SystemC:operation3\n");
    }
}

然后是外观对象 IFacade.class

public interface IFacade {
    void operationA();

    void operationB();

    void operationC();
}

Facade.class

public class Facade implements IFacade{

    private SystemA systemA = new SystemA();
    private SystemB systemB = new SystemB();
    private SystemC systemC = new SystemC();

    @Override
    public void operationA() {
        systemA.operation1();
        systemB.operation2();
        systemC.operation3();
    }

    @Override
    public void operationB() {
        systemA.operation2();
        systemB.operation1();
        systemC.operation3();
    }

    @Override
    public void operationC() {
        systemC.operation1();
        systemB.operation2();
        systemA.operation3();
    }
}

最后的测试代码:

public static void main(String args[]) {
    IFacade facade = new Facade();
    facade.operationA();
    facade.operationB();
    facade.operationC();
}

结果输出如下:
技术分享

示例与源码

  这里直接展示一段简单电脑启动时的伪代码来表示即可:

/* Complex parts */

class CPU {
    public void freeze() { ... }
    public void jump(long position) { ... }
    public void execute() { ... }
}

class Memory {
    public void load(long position, byte[] data) { ... }
}

class HardDrive {
    public byte[] read(long lba, int size) { ... }
}

/* Facade */

class ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hd;

    public ComputerFacade() {
        this.processor = new CPU();
        this.ram = new Memory();
        this.hd = new HardDrive();
    }

    public void start() {
        processor.freeze();
        ram.load(BOOT_ADDRESS, hd.read(BOOT_SECTOR, SECTOR_SIZE));
        processor.jump(BOOT_ADDRESS);
        processor.execute();
    }
}

/* Client */

class You {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

总结

  外观模式是一个高频率使用的设计模式,它的精髓就在于封装二字。通过一个高层次结构为用户提供统一的 API 入口,使得用户通过一个类型就基本能够操作整个系统,这样减少了用户的使用成本,也能够提升系统的灵活性。
  外观类遵循了一个很重要设计模式原则:迪米特原则(最少知识原则),它让客户端依赖于最少的类,直接依赖外观类而不是依赖于所有的子系统类。
  优点:

  • 对客户程序隐藏子系统细节,因而减少了客户对于子系统的耦合,能够拥抱变化;
  • 外观类对子系统的接口封装,使得系统更易于使用;
  • 更好的划分访问层次,通过合理使用Facade,可以帮助我们更好地划分访问的层次。有些方法是对系统外的,有些方法是系统内部使用的。把需要暴露给外部的功能集中到外观类中,这样既方便客户端使用,也很好地隐藏了内部的细节。
  缺点:
  • 外观类接口膨胀,由于子系统的接口都由外观类统一对外暴露,使得外观类的 API 接口较多,在一定程度上增加了用户使用成本;
  • 外观类没有遵循开闭原则,当业务出现变更时,可能需要直接修改外观类。

适配器 VS 装饰者 VS 桥接 VS 代理 VS 外观

  这几个都是结构型设计模式,他们有些类似,在实际使用过程中也容易搞混,我们在这就给他们做一个对比:

适配器模式

  适配器模式和其他三个设计模式一般不容易搞混,它的作用是将原来不兼容的两个类融合在一起,uml 图也和其他的差别很大。
  uml 类图:
  技术分享

装饰者模式

  装饰者模式结构上类似于代理模式,但是和代理模式的目的是不一样的,装饰者是用来动态地给一个对象添加一些额外的职责,装饰者模式为对象加上行为,而代理则是控制访问
  uml 类图:
  技术分享

桥接模式

  桥接模式的目的是为了将抽象部分与实现部分分离,使他们都可以独立地进行变化,所以说他们两个部分是独立的,没有实现自同一个接口,这是桥接模式与代理模式,装饰者模式的区别
  uml 类图:
  技术分享

代理模式

  代理模式为另一个对象提供代表,以便控制客户对对象的访问,管理的方式有很多种,比如远程代理和虚拟代理等,这个在上面有,这里就不说了,而装饰者模式则是为了扩展对象。
  uml 类图:
  技术分享

外观模式

  外观模式提供一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
  适配器模式将一个或多个类接口变成客户端所期望的一个接口,虽然大多数资料所采用的例子中适配器只适配一个类,但是你可以适配许多类来提供一个接口让客户端访问;类似的,外观模式 也可以只针对一个拥有复杂接口的类提供简化的接口,两种模式的差异,不在于他们“包装”了几个类,而是在于它们的意图。适配器模式 的意图是,“改变”接口符合客户的期望;而外观模式的意图是,提供子系统的一个简化接口。
  uml类图:
  技术分享

源码下载

  https://github.com/zhaozepeng/Design-Patterns/tree/master/FacadePattern

引用

https://en.wikipedia.org/wiki/Facade_pattern
http://blog.csdn.net/jason0539/article/details/22775311

java/android 设计模式学习笔记(14)---外观模式

标签:

原文地址:http://blog.csdn.net/self_study/article/details/51931196

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!