设计模式-外观模式

原文地址:LoveDev

外观模式(Facade Pattern):又称为门面模式,为一组接口提供一个统一的入口。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色降低原有系统的复杂度,同时降低客户端类与子系统的耦合度。

外观模式
外观模式
  • Facade(外观角色):外观角色中可以知道相关的多个子系统的功能和责任,客户端调用它的方法,它再传递给相应的子系统对象处理
  • SubSystem(子系统角色):子系统可以不是单独的类,而是类的集合,它实现子系统的功能,每个子系统都可以被客户端直接调用,或者被外观角色调用,对于子系统而言,外观角色也是一个客户端。

最近习惯了自己做饭,虽然做饭的过程很痛苦,可是看到自己做出来的美食后,还是很幸福很有成就感的。就拿自己做饭吃和去餐馆吃饭来举例,把餐馆看做外观角色,让它把买菜、切菜、炒菜、刷碗这些工作统一组织起来,我要做的就是告诉他要吃什么就行了,下面是示例代码:

SubSystem 类:

// 买菜
public class BuyVegetable {
    public void buy() {
        LogUtils.i("买菜");
    }
}

// 切菜
public class CutVegetable {
    public void cut() {
        LogUtils.i("切菜");
    }
}

// 炒菜
public class CookVegetable {
    public void cook() {
        LogUtils.i("炒菜");
    }
}

// 洗刷刷
public class WashDishes {
    public void wash() {
        LogUtils.i("洗刷刷");
    }
}

Facade 类:

// 餐馆
public class Restaurant {

    private final BuyVegetable mBuyVegetable;
    private final CutVegetable mCutVegetable;
    private final CookVegetable mCookVegetable;
    private final WashDishes mWashDishes;

    public Restaurant() {
        mBuyVegetable = new BuyVegetable();
        mCutVegetable = new CutVegetable();
        mCookVegetable = new CookVegetable();
        mWashDishes = new WashDishes();
    }

    public void eat() {
        mBuyVegetable.buy();
        mCutVegetable.cut();
        mCookVegetable.cook();
        mWashDishes.wash();
    }
}

Client 类:

// 自己做饭,需要跟这些子系统交互
BuyVegetable buyVegetable = new BuyVegetable();
CutVegetable cutVegetable = new CutVegetable();
CookVegetable cookVegetable = new CookVegetable();
WashDishes washDishes = new WashDishes();
buyVegetable.buy();
cutVegetable.cut();
cookVegetable.cook();
washDishes.wash();

// 去餐馆吃饭,只需跟餐馆交互
Restaurant restaurant = new Restaurant();
restaurant.eat();

有了外观模式,需要交互的类就变成了一个,让它负责和业务类实现交互,简化负责的交互,降低系统的耦合度,但是在标准的外观模式中,如果需要增删改外观类交互的子系统类,就需要改动客户端源码,这样就违反了“开闭原则”,因此遇到此类情况需要引入抽象外观类进行优化,还以上面例子为基础:

AbstarctFacade 类:

public abstract class AbstractFacade {
    public abstract void eat();
}

ConcreteFacade 类:

// 有些不用切就可以直接做的饭,比如面,这就需要把切菜移除掉
public class NoodlesRestaurant extends AbstractFacade{

    private final BuyVegetable mBuyVegetable;
    private final CookVegetable mCookVegetable;
    private final WashDishes mWashDishes;

    public NoodlesRestaurant() {
        mBuyVegetable = new BuyVegetable();
        mCookVegetable = new CookVegetable();
        mWashDishes = new WashDishes();
    }

    @Override
    public void eat() {
        mBuyVegetable.buy();
        mCookVegetable.cook();
        mWashDishes.wash();
    }
}

Client 类:

AbstractFacade abstractFacade = new NoodlesRestaurant();
abstractFacade.eat();

<h3> 优点 </h3>

  • 屏蔽子系统,减少客户端所需交互的对象,简化调用
  • 降低客户端与子系统耦合,面对子系统变化,只需要调整外观类即可
  • 子系统间的修改不会相互影响

<h3> 缺点 </h3>

  • 不能很好限制客户端直接使用子系统类,对访问子系统类做过多限制则减少可变性和灵活性
  • 设计不当时,增加新的子系统需要修改外观类源码,违背开闭原则

<h3> 使用场景 </h3>

  • 需要访问一系列子系统完成业务需求
  • 客户端和多个子系统很高的耦合,使用外观模式解耦,提高子系统的独立性和可移植性
  • 层次化结构中,使用外观模式定义系统中每层的入口,层与层之间不直接产生联系,通过外观类建立联系,降低层之间的耦合

源码地址:Github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 目录 本文的结构如下: 什么是外观模式 模式的结构 代码示例 优点和缺点 适用环境 模式应用 模式扩展 补充 一、...
    w1992wishes阅读 3,811评论 0 1
  • 文摘一:有些地方外观模式也被叫做门面模式,英文即Facade Pattern,提前说明一下。 试想这种情况,用户添...
    _浅墨_阅读 3,452评论 0 1
  • 1 场景问题# 1.1 生活中的示例## 外观模式在现实生活中的示例很多,比如:组装电脑,通常会有两种方案。 一个...
    七寸知架构阅读 11,445评论 7 57
  • 介绍 现实生活中有许多外观模式的例子,像餐馆的服务员、一些企业的客户人员、公司的前台等等。外观模式(Facade ...
    东西的南北阅读 1,709评论 0 0
  • 今天我们来学习另一种结构型模式,它就是外观模式(Facade Pattern)。 模式定义 外部与一个子系统的通信...
    HJXANDHMR阅读 3,550评论 0 4