Java设计模式:外观模式之优雅门面(九)

简介: Java设计模式:外观模式之优雅门面(九)

一、外观模式的起源与背景

在复杂的软件系统中,往往存在多个子系统或组件协同工作的情况。这些子系统可能由不同的团队开发,使用不同的技术栈,具有各自独特的接口和依赖关系。当客户端需要使用这些子系统时,可能需要了解并调用多个接口,处理复杂的依赖关系,这无疑增加了客户端的使用难度。

为了解决这个问题,外观模式应运而生。它通过一个外观类(Facade)来整合子系统中的接口,为客户端提供一个统一的、更简单的接口。客户端只需与外观类交互,而无需了解子系统的具体实现细节和复杂性。

二、外观模式的组件

2.1. Facade(外观类)

  • 外观类是外观模式的核心组件,它提供了客户端所需的统一接口。
  • 外观类内部持有对子系统对象的引用,负责将客户端的请求转发给相应的子系统对象处理。
  • 外观类可以对子系统的接口进行封装和抽象,使得客户端无需了解子系统的具体实现细节。
  • 外观类还可以对子系统的返回结果进行整合和处理,以更友好的方式呈现给客户端。

2.2. Subsystem Classes(子系统类)

  • 子系统类是实现具体功能的类,它们可能具有复杂的接口和相互依赖关系。
  • 在外观模式中,子系统类被隐藏起来,客户端不直接访问它们。而是通过外观类来间接访问子系统。
  • 子系统类之间可能存在复杂的交互和协作关系,但这些细节对客户端来说是透明的。

2.3. Client(客户端)

  • 客户端是使用外观类来访问子系统的类。
  • 客户端只需了解外观类提供的接口,而无需了解子系统的具体实现细节和复杂性。
  • 通过使用外观类,客户端可以更加简洁、方便地访问子系统,降低了客户端的使用难度和耦合度。

三、外观模式的优势分析

  1. 简化客户端使用:通过提供一个统一的接口,外观模式使得客户端可以更加简洁、方便地访问子系统。客户端无需了解子系统的复杂性和实现细节,只需调用外观类提供的方法即可完成操作。这降低了客户端的使用难度和学习成本。
  2. 降低耦合度:外观模式将客户端与子系统解耦,客户端只需与外观类交互,而无需直接依赖子系统。当子系统发生变化时,只需要修改外观类而无需修改客户端代码。这提高了系统的可维护性和可扩展性。
  3. 隐藏系统复杂性:外观类封装了子系统的实现细节和复杂性,为客户端提供了一个清晰的、一致的视图。这使得客户端可以专注于自己的业务逻辑,而无需关心子系统的具体实现和交互细节。这有助于保护子系统的内部结构和实现细节不被外部直接访问和修改。
  4. 提高系统灵活性:通过引入外观类作为中介层,我们可以更加灵活地组织和管理子系统。我们可以根据需要添加、删除或修改子系统的组件,而无需修改客户端代码。这提高了系统的灵活性和可配置性。

四、外观模式实现方式

我们模拟一个银行系统,其中包括账户管理、贷款服务和存款服务等多个子系统。然后使用外观模式来提供一个统一的接口给客户端使用。

首先,我们定义几个子系统类(Subsystem Classes),这些类模拟了银行系统中的不同组件。

// 账户管理子系统
class AccountManagement {
    public void createAccount(String accountName) {
        System.out.println("为 " + accountName + " 创建账户。");
    }

    public void closeAccount(String accountName) {
        System.out.println("关闭 " + accountName + " 的账户。");
    }
}

// 贷款服务子系统
class LoanService {
    public void applyForLoan(String accountName, double amount) {
        System.out.println(accountName + " 申请了 " + amount + " 的贷款。");
    }

    public void approveLoan(String accountName) {
        System.out.println(accountName + " 的贷款已被批准。");
    }
}

// 存款服务子系统
class DepositService {
    public void deposit(String accountName, double amount) {
        System.out.println(accountName + " 存款 " + amount + "。");
    }

    public void withdraw(String accountName, double amount) {
        System.out.println(accountName + " 取款 " + amount + "。");
    }
}

接下来,我们创建外观类(Facade),该类将封装这些子系统类,并为客户端提供一个统一的接口。

// 银行外观类
class BankFacade {
    private AccountManagement accountManagement;
    private LoanService loanService;
    private DepositService depositService;

    // 构造函数,初始化子系统对象
    public BankFacade() {
        accountManagement = new AccountManagement();
        loanService = new LoanService();
        depositService = new DepositService();
    }

    // 提供给客户端的简化方法 - 开户并存款
    public void openAccountAndDeposit(String accountName, double amount) {
        accountManagement.createAccount(accountName);
        depositService.deposit(accountName, amount);
        System.out.println("开户并存款操作完成。");
    }

    // 提供给客户端的简化方法 - 申请贷款并批准
    public void applyAndApproveLoan(String accountName, double amount) {
        loanService.applyForLoan(accountName, amount);
        loanService.approveLoan(accountName);
        System.out.println("申请并批准贷款操作完成。");
    }

    // 提供给客户端的简化方法 - 取款并关闭账户
    public void withdrawAndCloseAccount(String accountName, double amount) {
        depositService.withdraw(accountName, amount);
        accountManagement.closeAccount(accountName);
        System.out.println("取款并关闭账户操作完成。");
    }
}

最后,我们创建客户端(Client)来使用外观类。

// 客户端
public class BankClient {
    public static void main(String[] args) {
        // 创建银行外观对象
        BankFacade bankFacade = new BankFacade();

        // 客户端通过银行外观对象调用操作
        bankFacade.openAccountAndDeposit("张三", 10000);
        bankFacade.applyAndApproveLoan("张三", 5000);
        bankFacade.withdrawAndCloseAccount("张三", 2000);
    }
}

客户端通过BankFacade类的简化方法来完成一系列复杂的操作,如开户并存款、申请贷款并批准、取款并关闭账户等。客户端无需了解子系统的具体实现细节和它们之间的交互方式。

运行BankClient类的main方法,看到以下输出:

为 张三 创建账户。
张三 存款 10000.0。
开户并存款操作完成。
张三 申请了 5000.0 的贷款。
张三 的贷款已被批准。
申请并批准贷款操作完成。
张三 取款 2000.0。
关闭 张三 的账户。
取款并关闭账户操作完成。


通过银行外观类,客户端成功地完成了一系列复杂的银行业务操作,而无需直接与各个子系统打交道。这样的设计降低了客户端与子系统之间的耦合度,提高了系统的可维护性和可扩展性。

五、外观模式的应用场景举例

在大型软件系统中整合不同模块:在大型软件系统中,往往存在多个模块或组件协同工作的情况。这些模块可能由不同的团队开发,具有各自独特的接口和依赖关系。通过使用外观模式,我们可以将这些模块的接口整合成一个统一的接口,使得其他模块可以更加简洁、方便地访问它们。

隐藏复杂系统的实现细节:当一个系统的实现细节非常复杂时,我们可以使用外观模式来隐藏这些细节。通过提供一个简化的接口给客户端使用,我们可以保护系统的内部结构和实现细节不被外部直接访问和修改。这有助于确保系统的稳定性和安全性。

在分布式系统中整合服务:在分布式系统中,往往存在多个服务协同工作的情况。这些服务可能部署在不同的服务器上,具有各自独特的接口和通信协议。通过使用外观模式,我们可以将这些服务的接口整合成一个统一的接口,使得客户端可以更加简洁、方便地访问它们。这降低了客户端与分布式系统之间的通信复杂性和耦合度。

总结

外观模式是一种非常实用的设计模式,它通过引入一个统一的接口来隐藏系统的复杂性,使得客户端可以更方便地使用子系统。在实际应用中,我们应该根据具体的需求和场景来选择合适的设计模式,以提高软件系统的可维护性、可扩展性和可重用性。外观模式为我们提供了一个有效的手段来简化客户端的使用和降低系统的复杂性。

相关文章
|
22天前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
1月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
37 4
|
2月前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
52 0
[Java]23种设计模式
|
1月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
2月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
3月前
|
存储 设计模式 安全
Java设计模式-备忘录模式(23)
Java设计模式-备忘录模式(23)
|
3月前
|
设计模式 存储 算法
Java设计模式-命令模式(16)
Java设计模式-命令模式(16)
|
3月前
|
设计模式 存储 缓存
Java设计模式 - 解释器模式(24)
Java设计模式 - 解释器模式(24)
|
3月前
|
设计模式 安全 Java
Java设计模式-迭代器模式(21)
Java设计模式-迭代器模式(21)
|
3月前
|
设计模式 缓存 监控
Java设计模式-责任链模式(17)
Java设计模式-责任链模式(17)
下一篇
DataWorks