设计模式-外观模式

229 阅读3分钟

一、外观模式介绍

外观模式(Facade Pattern)也叫过程模式,它属于结构型模式。外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节,隐藏了系统的复杂性

这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用

外观类模式角色

  • 子系统的集合:指模块或者子系统,处理Facade对象指派的任务,它们是功能的实际提供者。
  • 外观类(Facade):为调用端提供统一的调用接口,外观类知道哪些子系统负责处理请求,从而将调用端的请求代理给适当子系统对象。

此处我们用一个示例来进行说明:

  • 诉求:通过调用各对象方法完成烹饪这一过程动作。
  • 传统模式下,我们会创建不同对象,不同方法让客户端进行过程的调用。(但该方式明显会给客户端调用增加使用成本)。
  • 解决方案:使用外观模式

二、外观模式使用

2.1 示例关系:

2.2 代码实现:

  • 各子系统对象
/* *
 * 蔬菜对象及相关操作步骤。
 */

class Vegetables {

    /* *
     * 饿汉式创建Vegetables实例。
     */

    private Vegetables() {
    }

    private static final Vegetables INSTANCE = new Vegetables();

    public static Vegetables getInstance() {
        return INSTANCE;
    }

    public void wash() {
        System.out.println(" 洗菜 ");
    }

    public void cut() {
        System.out.println(" 切菜 ");
    }

}


/* *
 * 肉对象及相关操作步骤。
 */

class Meat {

    /* *
     * 饿汉式创建Meat实例。
     */

    private Meat() {
    }

    private static final Meat INSTANCE = new Meat();

    public static Meat getInstance() {
        return INSTANCE;
    }

    public void cut() {
        System.out.println(" 切肉 ");
    }

    public void boil() {
        System.out.println(" 将肉焯水 ");
    }

}


/* *
 * 调料对象及相关操作步骤。
 */

class Flavour {

    /* *
     * 饿汉式创建Flavour实例。
     */

    private Flavour() {

    }

    private static final Flavour INSTANCE = new Flavour();

    public static Flavour getInstance() {
        return INSTANCE;
    }

    public void match() {
        System.out.println(" 搭配调料 ");
    }

    public void mix() {
        System.out.println(" 放入调料调味 ");
    }

}


/* *
 * 燃气灶对象及相关操作步骤。
 */

class GasStove {

    /* *
     * 饿汉式创建GasStove实例。
     */

    private GasStove() {
    }

    private static final GasStove INSTANCE = new GasStove();

    public static GasStove getInstance() {
        return INSTANCE;
    }

    public void on() {
        System.out.println(" 开火 ");
    }

    public void cooking() {
        System.out.println(" 炒菜中... ");
    }

    public void off() {
        System.out.println(" 关火 ");
    }

}
  • 外观类
/* *
 * 烹饪外观对象。
 * 1. 无参构造中调用各对象创建实例方法。
 * 2. 根据不同阶段,调用不同对象的操作步骤重新组合到新方法中。
 */

class CuisineFacade {
    
    private final Vegetables vegetables;
    private final Meat meat;
    private final Flavour flavour;
    private final GasStove gasStove;


    public CuisineFacade() {
        super();
        this.vegetables = Vegetables.getInstance();
        this.meat = Meat.getInstance();
        this.flavour = Flavour.getInstance();
        this.gasStove = GasStove.getInstance();
    }

    public void ready() {
        vegetables.wash();
        meat.boil();
        vegetables.cut();
        meat.cut();
        flavour.match();
    }

    public void start() {
        gasStove.on();
        gasStove.cooking();
        flavour.mix();
    }

    public void end() {
        gasStove.off();
    }
    
}

  • 客户端调用
public class Client {

    public static void main(String[] args) {
        CuisineFacade cuisineFacade = new CuisineFacade();

        cuisineFacade.ready();
        cuisineFacade.start();
        cuisineFacade.end();
        // 洗菜
        // 将肉焯水
        // 切菜
        // 切肉
        // 搭配调料
        // 开火
        // 炒菜中...
        // 放入调料调味
        // 关火
    }

}

三、外观模式总结

特点

  • 外观模式对外屏蔽了子系统的细节降低了客户端对于子系统使用的复杂度
  • 客户端和子系统解耦,使得子系统系统内部模块更易维护和拓展。
  • 通过合理地使用外观模式,可以帮助我们更好地划分访问层次

注意事项

  • 不能过多或者不合理使用外观模式。(无论使用外观模式或者直接调用模块,我们都要以系统有层次,利于维护为目的。)

应用场景

  • 维护遗留的大型系统时,可能系统变得难以拓展和维护,此时可以考虑外观模式,通过提供一个简单清晰的接口,让新系统与Facade类交互,提高复用性。
  • MyBatis中的Configuration类使用到了该模式。

四、结束语

“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶