• 【设计模式深度剖析】【6】【结构型】【外观模式】| 以电脑开关按钮为例,并结合微服务架构的API网关加深理解


    👈️上一篇:桥接模式    |   下一篇:享元模式👉️

    设计模式-专栏👈️

    外观模式(Facade Pattern)

    外观模式(Facade Pattern),如同一位精明的“外交官”,它简化了客户端与复杂子系统之间的交互,通过提供一个统一的“外交”接口,使得客户端无需深究子系统内部的“政治斗争”,从而降低了系统的复杂度,提高了代码的可维护性和可读性。

    ==>本文示例源码,点击查看👈️<==

    定义

    英文原文

    Facade Pattern provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

    直译

    外观模式为子系统中的一组接口提供了一个统一的接口。外观定义了一个更高层次的接口,使得子系统更加容易使用。

    如何理解呢?

    字面理解

    外观即外表、外观面,是事物对外展示的一面。

    代码实现中的理解

    在代码实现中,外观角色就像是系统的“外表”,它隐藏了内部的子系统细节,为客户端提供了一个统一的接口来访问子系统。

    生活案例:操作多功能料理机

    想象一下,当我们正在使用一个复杂的厨房设备,比如多功能料理机。这个料理机内部可能包含了榨汁机、搅拌机、研磨机等多种功能。

    但是,我们并不需要直接操作这些功能,只需要通过一个简单的控制面板就能完成我们想要的操作。

    这个控制面板就是外观模式的一个实际应用。它隐藏了料理机内部的复杂性,为我们提供了一个简单、直观的操作方式。

    同样地,在软件系统中,外观模式也为我们隐藏了复杂的内部结构和交互,使得我们能够更加方便地使用系统。

    典型案例分析:API网关与外观模式

    微服务架构中的API网关,为客户端提供了统一的访问入口,是进入系统的唯一节点,这与外观模式的定义相符。API网关封装了内部系统的架构,并且提供API给各个客户端。

    网关处理非业务逻辑(如认证、授权、负载均衡、缓存、熔断、降级、限流等),使得业务微服务更加专注于业务实现。

    具体表现为:

    1. 隐藏后端服务的复杂性

      在微服务架构中,后端通常包含多个独立的服务,每个服务都有自己的接口、功能和数据。这些服务之间可能存在复杂的依赖关系和交互逻辑。API网关作为一个中间件,隐藏了这些复杂性,为前端提供了一个统一、简洁的接口。前端开发者无需为每一个后端微服务单独配置地址和端口,只需要知道API网关的地址即可。因此,前端开发者无需关心后端服务的具体实现和部署情况,只需与API网关进行交互即可。

    2. 服务聚合

      当一个前端请求需要多个后端微服务协同处理时,API网关可以聚合这些微服务的响应,并将结果合并后返回给前端。

      API网关能够隐藏后端服务的复杂性,这减少了前端的复杂性,为前端提供一个简洁的响应,使得前端能够专注于与用户的交互和展示逻辑。

    3. 统一接口和协议

      API网关为前端提供了统一的接口和协议,使得前端开发者能够以统一的方式与后端服务进行通信。这样,即使后端服务的接口发生变化或新增了服务,只要API网关的接口保持不变,前端代码就无需修改。这种统一性减少了前端与后端之间的耦合度,使得前端可以更加灵活地与后端进行交互。

    4. 认证和授权

      API网关可以实施身份验证和授权机制,确保只有合法的用户、经过认证的请求才能访问后端服务。

      它可以通过OAuth2.0、JWT等技术实现用户认证和令牌管理,保护后端服务免受非法访问。API网关成为安全性的守护者,为后端服务提供一层保护。

    5. 限流和熔断

      API网关可以对流量进行限制,防止后端服务因过载而崩溃。

      当某个微服务出现故障时,API网关可以自动熔断对该微服务的调用,避免故障扩散到其他服务,避免级联故障的发生。

      API网关能够控制和管理后端服务的访问,确保系统的稳定性和可靠性。

    6. 路由和请求转发

      API网关能够根据预设的路由规则,将前端的请求转发到后端对应的服务上。这种路由机制使得前端无需关心后端服务的具体地址和端口,只需发送请求到API网关即可。同时,API网关还可以根据服务的负载情况、健康状况等因素进行负载均衡和容错处理,进一步降低前端与后端之间的耦合度。

    7. 负载均衡

      一个网关可以接收多个服务实例,因此网关需要在各个对等的服务实例上做负载均衡策略。

    8. 降低服务间的耦合度

      通过将非业务逻辑(如路由、转发、认证、授权、熔断、限流等)放在API网关中实现,可以使得后台业务微服务更加专注于业务逻辑的实现,实现业务与技术的解耦。

      通过API网关的路由转发机制,前端与后端之间的耦合度被大大降低。前端开发者无需关心后端服务的具体实现和部署情况,只需与API网关进行交互即可。同时,后端服务无需直接关注前端发送的具体请求细节,包括请求的参数、格式等,同时也无需直接处理针对前端的响应格式。它们只需按照与API网关或其他服务调用者约定的接口规范,处理接收到的请求数据,并返回符合规范的数据格式。

    9. 日志和监控

      API网关可以记录所有经过的请求日志,方便后续的故障排查、性能分析和安全审计。

      收集API的调用量、响应时间、错误率等关键指标,为系统监控和性能调优提供数据支持。

    通过外观模式的实现,API网关在前后端分离的微服务架构中发挥着至关重要的作用。它简化了前端的配置和开发过程,提高了系统的可扩展性、可靠性和安全性。同时,API网关还提供了路由、认证、限流、监控等核心功能,使得微服务架构更加完善和高效。

    外观模式角色

    UML类图

    在这里插入图片描述

    外观(Facade)

    为子系统中的一组接口提供一个一致的界面,此界面使得这一子系统更加容易使用。

    子系统(Subsystem)

    实现系统的部分功能,客户可以通过外观角色与其进行交互。

    客户(Client)

    通过外观角色与子系统交互,使用子系统的功能。

    代码示例

    子系统角色:SubsystemOne

    package com.polaris.designpattern.list2.structural.pattern6.facade.classicdemo;
    
    // 子系统角色:SubsystemOne
    public class SubsystemOne {
        public void methodOne() {
            System.out.println("SubsystemOne: Method 1 executed.");
        }
    }  
    

    子系统角色:SubsystemTwo

    package com.polaris.designpattern.list2.structural.pattern6.facade.classicdemo;
    
    // 子系统角色:SubsystemTwo  
    public class SubsystemTwo {
        public void methodTwo() {
            System.out.println("SubsystemTwo: Method 2 executed.");
        }
    }  
    

    外观角色:Facade

    package com.polaris.designpattern.list2.structural.pattern6.facade.classicdemo;
    
    // 外观角色:Facade  
    public class Facade {
        private SubsystemOne subsystemOne;
        private SubsystemTwo subsystemTwo;
    
        public Facade() {
            subsystemOne = new SubsystemOne();
            subsystemTwo = new SubsystemTwo();
        }
    
        // 提供单独调用子系统一的方法  
        public void operationOne() {
            subsystemOne.methodOne();
        }
    
        // 提供单独调用子系统二的方法  
        public void operationTwo() {
            subsystemTwo.methodTwo();
        }
    
        // 提供同时调用两个子系统方法的方法  
        public void operation() {
            operationOne();
            operationTwo();
        }
    }  
    

    客户端角色:Client

    package com.polaris.designpattern.list2.structural.pattern6.facade.classicdemo;
    
    
    // 客户端角色:Client  
    public class Client {
        public static void main(String[] args) {
            Facade facade = new Facade();
    
            // 单独调用子系统一的方法  
            facade.operationOne();
            System.out.println("------------------");
    
            // 单独调用子系统二的方法  
            facade.operationTwo();
            System.out.println("------------------");
    
            // 同时调用两个子系统的方法  
            facade.operation();
        }
    }
    /* Output:
    SubsystemOne: Method 1 executed.
    ------------------
    SubsystemTwo: Method 2 executed.
    ------------------
    SubsystemOne: Method 1 executed.
    SubsystemTwo: Method 2 executed.
    *///~
    

    外观模式的应用

    外观模式就像是我们日常生活中使用的智能手机界面。手机内部可能包含了各种复杂的硬件和软件,但对外,我们只需要通过一个简单、直观的界面就能完成打电话、发信息、拍照、上网等各种功能。这个界面就是外观模式的一个应用,它隐藏了内部的复杂性,为用户提供了一个统一的、简单的操作方式。

    外观模式的优点

    1. 简化操作:外观模式为用户提供了一个统一的接口,用户无需了解内部复杂的结构,只需通过外观接口就能完成所需的操作。
    2. 降低耦合度:外观模式使得子系统之间的耦合度降低,因为它们之间的交互都是通过外观接口进行的,而不是直接交互。
    3. 提高灵活性:当子系统内部发生变化时,只需要修改外观接口的实现,而无需修改客户端代码,提高了系统的灵活性。

    外观模式的缺点

    1. 增加复杂性:在某些情况下,如果设计不当,外观类可能会变得非常复杂,从而增加了系统的复杂性。
    2. 依赖风险:由于客户端都依赖于外观接口,因此如果外观接口设计不合理或出现问题,可能会导致整个系统的崩溃。

    外观模式的使用场景

    1. 子系统之间交互复杂:当系统内部有多个子系统,并且子系统之间的交互非常复杂时,可以使用外观模式来简化它们之间的交互。
    2. 需要隐藏子系统细节:在某些情况下,我们可能不希望用户或客户端直接访问子系统的内部细节。此时,可以使用外观模式来隐藏这些细节,只提供一个统一的接口供用户访问。
    3. 提高系统灵活性和可扩展性:当系统需要经常添加或删除子系统时,使用外观模式可以使得客户端代码不随子系统的变化而变化,从而提高了系统的灵活性和可扩展性。

    示例解析:电脑开关按钮

    ==>本文示例源码,点击查看👈️<==

    我们可以使用“电脑开关机”作为一个更简单且常见的外观模式例子。

    电脑内部有很多复杂的硬件和软件组件,如处理器、内存、硬盘、操作系统等。但是,当我们想要打开电脑或关闭电脑时,我们并不需要直接与这些组件交互,而是通过一个统一的接口——电源开关按钮来完成。

    我们并不需要了解电脑内部复杂的构造和工作原理,只需要按下电源开关按钮,电脑就会开始启动;再次按下按钮,电脑就会关机。

    电源开关按钮就是外观模式的一个实际应用,它隐藏了电脑内部复杂的启动和关闭过程,为用户提供了一个简单、直观的操作方式。

    代码示例

    UML类图

    在这里插入图片描述

    子系统角色:电脑内部的复杂组件

    package com.polaris.designpattern.list2.structural.pattern6.facade.computerfacade;
    
    // 电脑内部的复杂组件(这里只是示意)
    public class ComputerHardware {
        public void startUp() {
            System.out.println("Starting up the computer...");
            // 这里会执行一系列复杂的启动过程,如加载操作系统、初始化硬件等  
        }
    
        public void shutDown() {
            System.out.println("Shutting down the computer...");
            // 这里会执行一系列复杂的关闭过程,如保存数据、关闭应用程序、关闭硬件等  
        }
    }  
    

    外观类(电源开关按钮)

    package com.polaris.designpattern.list2.structural.pattern6.facade.computerfacade;
    
    // 外观类(电源开关按钮)
    public class PowerButton {
        private ComputerHardware hardware;
    
        public PowerButton() {
            hardware = new ComputerHardware();
        }
    
        // 统一的接口,用户只需调用此方法即可启动电脑  
        public void pressToStart() {
            hardware.startUp();
        }
    
        // 统一的接口,用户只需调用此方法即可关闭电脑  
        public void pressToShutDown() {
            hardware.shutDown();
        }
    }  
      
    

    客户端

    package com.polaris.designpattern.list2.structural.pattern6.facade.computerfacade;
    
    
    // 客户端代码(用户)  
    public class User {
        public static void main(String[] args) {
            PowerButton powerButton = new PowerButton();
            powerButton.pressToStart(); // 启动电脑  
            // ... 用户使用电脑 ...  
            powerButton.pressToShutDown(); // 关闭电脑  
        }
    }
    
    /* Output:
    Starting up the computer...
    Shutting down the computer...
    *///~
    

    在这个代码示例中,

    ComputerHardware 类代表电脑内部的复杂组件,它提供了启动和关闭电脑的方法。

    PowerButton 类是外观类,它隐藏了电脑内部复杂的启动和关闭过程,并为用户提供了一个统一的接口——电源开关按钮。

    用户(即客户端)只需要与 PowerButton 类交互,就能控制电脑的启动和关闭,而无需关心电脑内部是如何工作的。

    👈️上一篇:桥接模式    |   下一篇:享元模式👉️

    设计模式-专栏👈️

  • 相关阅读:
    Power BI 傻瓜入门 5. 准备数据源
    ROG幻15电脑开机自动安装软件怎么U盘重装系统
    猿创征文 | 【Java进阶】详解抽象类及常用接口
    yolo报错indexerror: list index out of range
    POJ 1975 (传递闭包)
    如何 build 一个 mysql_client 镜像
    MyBatis源码基础-常用类-Configuration
    Listen、Attention、Spell模型
    网络安全(黑客)自学
    深度学习面试题
  • 原文地址:https://blog.csdn.net/qq_28727015/article/details/139280993