当前位置: 首页 > news >正文

设计模式第五章(门面模式)

设计模式第五章(门面模式)

​ 门面模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供了一个统一的高层接口,使得子系统更容易使用。

门面模式主要包含以下几个角色:

  • Facade(门面角色):是门面模式的核心,为子系统提供统一接口,屏蔽子系统的复杂性。它知道哪些子系统负责处理请求,并将请求代理给适当的子系统对象。
  • SubSystem Classes(子系统角色):实现子系统的功能,这些子系统对客户端来说是黑盒,客户端通过门面角色与它们交互。
  • Client(客户角色):与门面角色交互,无需了解子系统的具体实现。

​ 例如,在一个电商系统中,订单处理涉及库存系统、支付系统、物流系统等多个子系统。可以设计一个订单处理门面,将这些子系统的功能整合在一起,客户端只需与订单处理门面交互,无需了解库存、支付、物流等子系统的具体实现细节,就能完成订单处理的操作。

门面模式的优点包括简化客户端调用、减少系统依赖、提高代码的可维护性和可读性等。缺点是不符合开闭原则,当增加子系统和扩展子系统行为时,可能需要修改门面类,并且在某些情况下,可能会导致门面类变得庞大,承担过多的责任。

引言

我们模拟一个mysql 和tomcat 的启动过程,mysql 的启动过程是不是分为好几个步骤,tomcat 启动是不是也分为多个步骤,接下来我们用代码表示一下。

mysql 启动过程

public class Mysql {public void initData() {System.out.println("初始化mysql......");}public void checkLog() {System.out.println("校验日志,恢复未提交的数据......");}public void unlock() {System.out.println("释放锁");}public void listerPort() {System.out.println("监听端口 3306 ");}
}

tomcat 启动过程

public class MyTomcat {public void initEngine() {System.out.println("初始化tomcat引擎....");}public void initWeb() {System.out.println("加载web应用。。。");}
}

客户端调用

public class Main {public static void main(String[] args) {Mysql mysql = new Mysql();mysql.initData();mysql.checkLog();mysql.unlock();mysql.listerPort();System.out.println("-------------->");MyTomcat tomcat = new MyTomcat();tomcat.initEngine();tomcat.initWeb();}
}

在这里插入图片描述

问题点

​ 我们看到,作为第一个客户端,我们调用需要经过多个步骤,有没有一种简单的方法,我们只需要调用,某一个方法就能实现这种场景呢,那么接下来就是一个门面的封装了。

门店模式封装启动过程

  • 抽象启动类
  • 实现类

抽象类

我们定义了一个抽象启动的门店接口,里面只有一个方法,start()

public interface ServiceFace {void start();
}

mysql 实现

public class MySql1 implements ServiceFace {@Overridepublic void start() {Mysql mysql = new Mysql();mysql.initData();mysql.checkLog();mysql.unlock();mysql.listerPort();}
}

tomcat实现

public class MyTomcat1 implements ServiceFace {@Overridepublic void start() {MyTomcat tomcat = new com.fashion.ori.MyTomcat();tomcat.initEngine();tomcat.initWeb();}
}

客户端

public class Main {public static void main(String[] args) {ServiceFace tomcat = new MyTomcat1();tomcat.start();ServiceFace mysql = new MySql1();mysql.start();}
}

在这里插入图片描述

我们看到,调用的客户端只需要知道门面接口定义的抽象方法即可,这样调用的过程封装到实现里面,使客户端使用更简单。

自定义门面插件类

需求背景,我需要统计一个接口每次被调用都进行一个计次数的动作,当然我们可以直接写到方法中,但是如果这是一个插件呢,我们需要如何实现。

  • 插件api 模块
  • 插件实现类
  • 调用方

插件api

public interface MyPlugin {void beforeGetTime();
}
    <modelVersion>4.0.0</modelVersion><groupId>com.fashion</groupId><artifactId>my_plugin_api</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>

插件实现类

public class CountPlugin implements MyPlugin {AtomicInteger count = new AtomicInteger(0);@Overridepublic void beforeGetTime() {System.out.println("访问次数:"+count.incrementAndGet());}
}
    <artifactId>count_plugin</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>com.fashion</groupId><artifactId>my_plugin_api</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies></project>

客户端

@RestController
public class TimeController {private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");private MyPlugin myPlugin;@GetMapping("/time")public String getTime() {if (myPlugin != null) {myPlugin.beforeGetTime();}return LocalDateTime.now().format(dateTimeFormatter);}/***  加载插件  必须有一个文件叫 liuqiang.plug*/@GetMapping("/load/plugin/{path}")public String loadPlugin(@PathVariable("path") String path) {File file = new File("face-pattern\\face-boot\\"+path);try(URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toPath().toUri().toURL()});InputStream lqPlugin = urlClassLoader.getResourceAsStream("chajian.plugin");) {//插件的实现类String myPluginClassName = new String(lqPlugin.readAllBytes());Class<?> aClass = urlClassLoader.loadClass(myPluginClassName.trim());// 生成构建方法Constructor<?> constructor = aClass.getConstructor();myPlugin = (MyPlugin)constructor.newInstance();return "插件加载成功----"+aClass.getName();} catch (Exception e) {return "插件记载失败"+e.getMessage();}}}

pom文件

 <properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.fashion</groupId><artifactId>my_plugin_api</artifactId><version>1.0-SNAPSHOT</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><mainClass>com.fashion.face.FaceBootApplication</mainClass><skip>true</skip></configuration><executions><execution><id>repackage</id><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>

启动流程

我们先加载插件,当插件加载后,那么我们访问 time 接口就会调用插件中的实现方法

在这里插入图片描述

在这里插入图片描述

调用接口

在这里插入图片描述

在这里插入图片描述

http://www.dtcms.com/a/418653.html

相关文章:

  • 海康相机SDK封装
  • 大模型应用:一个基于AI大模型的自动邮件简报系统 - Flask + HTML 方案
  • 开源 C# 快速开发(八)通讯--Tcp服务器端
  • MTK调试-电池识别
  • 网站目标网页制作下载图片代码
  • 钱站网站如何建设手机移动网站
  • Vue调用浏览器打印
  • 捷讯官网 网站建设网站到期只续域名不续空间能打开吗
  • CS231n学习笔记1-4: Image Features
  • DragonBalls_One009*
  • extern关键字
  • 捷为科技亮相新能源汽车产业对接会,数智化平台赋能汽车行业高质量发展
  • ChatBI 学习
  • 百度网站推广咨询建筑网人才
  • 桂林网站建设服务网站定制牛七科技
  • WebRTC 发送端 SSRC 生成流程总结
  • 客户标签自动管理:标签自动化运营,画像持久保鲜
  • 云原生架构与GitOps技术栈介绍
  • 智能外呼产品架构组成
  • 【深度学习新浪潮】如何提升agent的专业性?
  • AI排名查询工具如何助力GEO优化?生成引擎优化中的关键词竞争力分析
  • 福州有网站建设的公司网站都需要什么类别
  • Nginx 反向代理与负载均衡核心内容总结
  • JavaWeb 课堂笔记 —— 20 SpringBootWeb案例 配置文件
  • 算法练习题
  • 9.数组介绍和静态初始化
  • 无重复字符的最长子串_优选算法(C++)滑动窗口
  • 提升雾化片性能,关键是精密测量盲孔尺寸
  • Flannel工作原理-Flannel故障案例-镜像拉取策略-secret对接harbor及ServiceAccount实战
  • GitLab高危漏洞可致实例崩溃(CVE-2025-10858 和 CVE-2025-8014)