您现在的位置是:首页 >技术杂谈 >结构型设计模式03-外观模式网站首页技术杂谈

结构型设计模式03-外观模式

猫十二懿 2024-07-12 12:01:07
简介结构型设计模式03-外观模式

✨作者:猫十二懿

❤️‍?账号:CSDN掘金个人博客Github

?公众号:猫十二懿

外观模式(门面模式)

1、外观模式介绍

外观模式(Facade Pattern),也称门面模式,是一种结构型设计模式,它==为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用,==从而使子系统更易用、更易懂、更易扩展。

外观模式的核心思想是封装,即将一组复杂的类或接口封装在一个外观类中,客户端只与外观类进行交互,而不直接与复杂的子系统进行交互。外观类隐藏了子系统的复杂性,客户端只需要知道如何使用外观类提供的接口即可。

1.2 外观模式结构图

image-20230423224113890

四个子系统的类:

外观类:

客户端调用:

image-20230423224238714

对于面向对象有一定基础的朋友,即使没有听说过外观模式,也完全有可能在很多时候使用它,因为它完美地体现了依赖倒转原则和迪米特法则的思想

2、案例说明

例子:牛市股票,购买不同的股票、债卷等(不是教大家去炒股哦,禁止黄赌毒!!!

2.1 不使用外观模式

先来看看这个炒股程序的UML 类图

image-20230423221609095

具体实现程序:

/**
 * @author Shier
 * CreateTime 2023/4/23 22:18
 */
public class FacadeTest {
    public static void main(String[] args) {
        Stock1 stock1 = new Stock1();
        Stock2 stock2 = new Stock2();
        NationDebt1 nationDebt = new NationDebt1();
        Realty1 realty1 = new Realty1();
        // 用户需要了解了股票这些的情况,并且参与了这些项目的具体买和卖,之间的耦合性高
        realty1.buy();
        stock2.buy();
        stock1.buy();
        nationDebt.buy();

        stock1.sell();
        stock2.sell();
        nationDebt.sell();
        realty1.sell();
    }
}
// 股票一
class Stock1{
    // 卖股票
    public void sell(){
        System.out.println("股票一售出");
    }
    //买股票
    public void buy(){
        System.out.println("股票一买入");
    }
}
// 股票二
class Stock2{
    // 卖股票
    public void sell(){
        System.out.println("股票二售出");
    }
    //买股票
    public void buy(){
        System.out.println("股票二买入");
    }
}
// 国债一
class NationDebt1{
    // 卖国债
    public void sell(){
        System.out.println("国债一售出");
    }
    //买国债
    public void buy(){
        System.out.println("国债一买入");
    }
}

// 房地厂一
class Realty1{
    // 卖房地厂
    public void sell(){
        System.out.println("房地产一售出");
    }
    // 买房地厂
    public void buy(){
        System.out.println("房地厂一买入");
    }
}

由于众多投资者对众多股票的联系太多,反而不利于操作,导致了耦合性过高。

2.2 使用外观模式

再来修改投资的UML 结构类图

image-20230423222923354

基金类:

package com.shier.facade;

import java.util.Scanner;

/**
 * @author Shier
 * CreateTime 2023/4/23 22:30
 * 买入卖出的操作在基金类完成,就不用用户关心
 * 也就是说基金类需要了解到市场股票等项目的买入卖出情况,以备用户知道
 */
public class Fund {
    Stock1 stock1;
    Stock2 stock2;
    NationDebt1 nationDebt1;
    Realty1 realty1;

    public Fund() {
        stock1 = new Stock1();
        stock2 = new Stock2();
        nationDebt1 = new NationDebt1();
        realty1 = new Realty1();
    }

    //基金类购买
    public void buyFund() {
        stock1.buy();
        stock2.buy();
        nationDebt1.buy();
        realty1.buy();
    }
    //基金类销售
    public void sellFund() {
        stock1.sell();
        stock2.sell();
        nationDebt1.sell();
        realty1.sell();
    }
}

客户端调用基金类的买入卖出:

/**
 * @author Shier
 * CreateTime 2023/4/23 22:18
 */
public class FacadeTest {
    public static void main(String[] args) {
        Fund fund = new Fund();
        // 基金完成购买
        fund.buyFund();
        // 基金赎回
        fund.sellFund();
    }
}

其他的股票等类就不要再去修改了。

最后的结果:

image-20230423223636413

而有了基金以后,变成众多用户只和基金打交道,关心基金的上涨和下跌就可以了,而实际上的操作却是基金经理人在与上千支股票和其他投资产品打交道。

这样就通过了基金类完成了所有的买入卖出操作,用户就不要再去关心那么多信息,降调了耦合度。

3、总结

3.1 何时使用外观模式

  1. 在设计初期阶段,应该要有意识地将不同的两个层分离。比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。
  2. 在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂。大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。
  3. 在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时用外观模式Facade也是非常合适的。

为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作。

3.2 外观模式优缺点

外观模式的优点包括:

  1. 简化了客户端代码:外观模式提供了一个统一的接口,客户端只需要调用外观类提供的方法即可完成复杂的操作,避免了直接调用多个子系统类的情况,从而简化了客户端代码。

  2. 降低了耦合度:由于外观模式将客户端与子系统解耦,使得子系统的变化对客户端的影响降到最低,从而提高了系统的可维护性、可扩展性和灵活性。

  3. 隐藏了复杂性:外观模式将复杂的子系统封装在外观类中,客户端不需要了解子系统的实现细节,从而降低了系统的复杂度,让客户端能够更加轻松地使用该系统。

外观模式的缺点包括:

  1. 不能很好地限制客户端使用子系统类:由于外观模式只是封装了一部分子系统的功能,而并未限制客户端直接使用子系统类,所以客户端可能会绕过外观类直接使用子系统类,从而导致系统的混乱和不稳定。

  2. 增加了系统的复杂度:外观模式需要增加一个外观类来封装子系统,这样就会增加系统的复杂度和代码量。

3.3 外观模式适用情况

  1. 当一个复杂的子系统需要被简化并分层时,可以使用外观模式来定义其关键子系统之间的接口,从而保证它们之间的协作和互操作。

  2. 当客户端与一个复杂的子系统的通信过程较为复杂时,可以使用外观模式来隐藏子系统的复杂性,以便客户端能够更加轻松地与该系统进行通信。

  3. 当需要将一个复杂的系统划分为多个子系统时,可以使用外观模式来分别定义这些子系统之间的关系和通信方式,从而让系统更加可维护和易扩展。

在外观模式中,关键角色包括外观类(Facade)、子系统类(Subsystem)、客户端(Client)等。其中,外观类是使用该模式的核心,它封装了子系统的各种复杂操作,并向客户端提供简单的接口。客户端只需要调用外观类的接口,就可以完成相应的操作。子系统类则是实现了各种具体操作的类,外观类会调用子系统类来完成实际的业务逻辑。

要将一个复杂的系统划分为多个子系统时,可以使用外观模式来分别定义这些子系统之间的关系和通信方式,从而让系统更加可维护和易扩展。

在外观模式中,关键角色包括外观类(Facade)、子系统类(Subsystem)、客户端(Client)等。其中,外观类是使用该模式的核心,它封装了子系统的各种复杂操作,并向客户端提供简单的接口。客户端只需要调用外观类的接口,就可以完成相应的操作。子系统类则是实现了各种具体操作的类,外观类会调用子系统类来完成实际的业务逻辑。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。