解锁Spring Boot中的设计模式—04.桥接模式:探索【桥接模式】的奥秘与应用实践!

桥接模式

桥接模式也称为桥梁模式、接口模式或者柄体(Handle and Body)模式,是将抽象部分与他的具体实现部分分离,使它们都可以独立地变化,通过组合的方式建立两个类之间的联系,而不是继承。

桥接模式是一种结构型设计模式,旨在将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过使用组合而不是继承的方式,可以更灵活地组织和管理代码。

结构:

  • 抽象部分(Abstraction):定义抽象类或接口,并维护一个指向实现部分的引用。
  • 扩充抽象类(Refined Abstraction):扩展抽象部分,可以添加更多的功能。
  • 实现部分(Implementor):定义实现类接口,供抽象部分调用。
  • 具体实现类(Concrete Implementor):实现实现部分的接口,提供具体的功能实现

优点:

  1. 解耦合:桥接模式能够将抽象部分和实现部分分离,使它们可以独立地进行变化。这种解耦合使得系统更加灵活和可维护。
  2. 扩展性:由于桥接模式采用了组合的方式而不是继承,因此更容易扩展和变化。新的抽象部分和实现部分可以独立地添加和修改,而不会对现有的代码产生影响。
  3. 隐藏实现细节:桥接模式可以隐藏实现的细节,使客户端代码只关注于抽象部分,而不需要关心具体的实现细节。这种隐藏可以减少系统中的耦合度,提高代码的可维护性和可理解性。
  4. 适应变化:桥接模式使得系统更加灵活和适应变化。通过抽象部分和实现部分的分离,系统可以更容易地应对需求的变化和新的功能的添加。

缺点:

  1. 增加复杂性:桥接模式引入了抽象部分和实现部分之间的桥梁,可能会增加系统的复杂性。特别是对于简单的系统,使用桥接模式可能会显得过于复杂。
  2. 理解成本:由于桥接模式涉及到多个类和接口之间的关系,可能会增加新成员对系统的理解成本。需要仔细地理解抽象部分和实现部分之间的关系,以及桥接模式的设计思想。
  3. 过度设计:在某些情况下,使用桥接模式可能会导致过度设计的问题。如果系统的抽象部分和实现部分之间的关系比较简单,使用桥接模式可能会显得不够自然和合适。
  4. 设计复用性:虽然桥接模式提高了系统的灵活性和扩展性,但如果不恰当地使用,可能会导致设计复用性下降。过度使用桥接模式可能会导致代码结构的过度抽象,使得代码变得难以理解和维护。

注意事项

  • 桥接模式适用于系统中多个维度的变化。
  • 避免过度设计,只有当两个维度中的一个或两个具有多个实现时才考虑使用桥接模式。

适用场景

  • 系统有多个维度同时变化,且不希望使用多层继承。
  • 想要在抽象和实现之间建立一个稳定的联系,但又不希望二者紧密耦合。

1.案例1-发送通知

需求

假设我们正在开发一个电商平台,该平台需要发送不同类型的通知给用户,例如电子邮件通知、短信通知、App推送通知等。同时,用户可能也有不同的偏好和设备,例如有些用户更喜欢通过邮件接收通知,而另一些用户则更倾向于使用手机App接收通知。

实现思路

  1. 通知接口(Notification):定义了发送通知的方法。
  2. 具体通知类(ConcreteNotification):实现了通知接口的具体通知类型,如邮件通知、短信通知、App推送通知等。
  3. 用户偏好(UserPreference):定义了用户的通知偏好,包含具体通知类,例如用户更喜欢接收邮件通知还是App推送通知。
  4. 用户类(User)包含用户的信息和偏好设置
  5. 通知服务类(NotificationService):负责根据用户的偏好选择合适的通知方式进行发送。(包含用户信息
Notification
+sendNotification(message)
EmailNotification
+sendNotification(message)
SMSNotification
+sendNotification(message)
AppNotification
+sendNotification(message)
UserPreference
+getNotification()
User
-preference: UserPreference
+receiveNotification(message)
NotificationService
+sendNotificationToUser(user, message)

在这里插入图片描述

1.1.通知接口
/*** 通知接口* @author 13723* @version 1.0* 2024/2/7 10:17*/
public interface Notification {/*** 通知* @param message 通知消息*/void notify(String message);
}
1.1.2.具体通知类-APP
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** APP通知类* @author 13723* @version 1.0* 2024/2/7 10:19*/
public class APPNotification implements Notification{private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** APP通知* @param message 通知消息*/@Overridepublic void notify(String message) {logger.error("【APP通知】: {}", message);}
}
1.1.3.具体通知类-短信
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** 邮箱通知类* @author 13723* @version 1.0* 2024/2/7 10:21*/
public class EMailNotification implements Notification{private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 邮箱通知* @param message 通知消息*/@Overridepublic void notify(String message) {logger.error("【邮件通知】: {}", message);}
}
1.1.4.具体通知类-邮箱
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** 邮箱通知类* @author 13723* @version 1.0* 2024/2/7 10:21*/
public class EMailNotification implements Notification{private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 邮箱通知* @param message 通知消息*/@Overridepublic void notify(String message) {logger.error("【邮件通知】: {}", message);}
}
1.1.5.用户偏好类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** 用户偏好类* @author 13723* @version 1.0* 2024/2/7 10:23*/
public class UserPreference {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 此处引入通知接口,实现桥接模式,将通知接口和用户偏好类解耦*/private Notification notification;/*** 用户偏好* @param notification 通知*/public UserPreference(Notification notification) {this.notification = notification;}public Notification getNotification() {return notification;}
}
1.1.6.用户类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** 用户类* @author 13723* @version 1.0* 2024/2/7 10:26*/
public class User {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 用户名称*/private String name;/*** 用户偏好*/private UserPreference userPreference;public User(String name, UserPreference userPreference) {this.name = name;this.userPreference = userPreference;}protected void receiveNotification(String message) {message = name + ":" + message;userPreference.getNotification().notify(message);}}
1.1.7.服务通知类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** @author 13723* @version 1.0* 2024/2/7 10:37*/
public class NotificationService {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());/*** 发送通知* @param user 用户,用户里面已经设置好偏好通知了,偏好通知里面已经设置好具体的通知方式了* @param message 通知消息*/public void sendNotification(User user, String message) {user.receiveNotification(message);}
}
1.1.8.测试类
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.invoke.MethodHandles;/*** 测试 桥梁模式-通知用户* @author 13723* @version 1.0* 2024/2/7 10:42*/
public class NotificationTest {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());@Test@DisplayName("测试通知用户")public void testNotification() {// 设置通知方式APPNotification appNotification = new APPNotification();SMSNotification smsNotification = new SMSNotification();// 设置用户偏好UserPreference zs = new UserPreference(appNotification);UserPreference ls = new UserPreference(smsNotification);// 设置用户User user1 = new User("张三", zs);User user2 = new User("李四", ls);// 通知服务NotificationService notificationService = new NotificationService();notificationService.sendNotification(user1, "你好,你的账号被人盗走了!请联系客户找回,85852555!");notificationService.sendNotification(user2, "你好,你的账号被人盗走了!请联系客户找回,85852555!");}
}

在这里插入图片描述

2.Spring代码-JdbcTemplate

2.1.案例

@SpringBootTest
public class BridgeTest {private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());@Test@DisplayName("测试template")public void test(){DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("org.postgresql.Driver");dataSource.setUrl("jdbc:postgresql://192.168.1.56/postgres?currentSchema=gwstd");dataSource.setUsername("postgres");dataSource.setPassword("152564.lmy");JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);String sql = "select * from t_dec_order_head limit 1";List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);for (Map<String, Object> map : maps) {logger.error("result:{}",map);}}
}

在这里插入图片描述

JdbcTemplate 使用了桥接模式来实现数据库操作的抽象和实现的解耦合。这种模式使得应用程序能够专注于高级的业务逻辑,而不必关心底层数据库访问的细节。

JdbcTemplate 使用了以下几个关键角色:

  1. 抽象部分(Abstraction)
    • JdbcTemplate 中,抽象部分代表了对数据库操作的抽象接口,例如 JdbcTemplate 类本身以及它的一些方法,如 query()update() 等。
    • 这些方法定义了客户端与数据库交互的高级操作,比如查询数据、更新数据等。
  2. 扩充抽象类(Refined Abstraction)
    • 在 JdbcTemplate 中,扩充抽象部分是对抽象部分的扩展,可以添加更多的功能或者调整现有的功能。
    • 例如,你可以创建自定义的 JdbcTemplate 子类,通过添加新的方法或者重写现有方法来实现更具体的数据库操作。
  3. 实现部分(Implementor)
    • JdbcTemplate 中,实现部分代表了对底层数据库访问的实现,例如 DataSource 接口和各种数据库驱动实现。
    • 这些实现提供了底层的数据库连接和操作功能,但不暴露给应用程序直接使用。
  4. 具体实现类(Concrete Implementor)
    • 具体实现类是实现部分的具体实现,比如 DriverManagerDataSourceC3P0DataSource 等。
    • 它们提供了具体的数据库连接池实现、连接配置等功能。
// 在创建JDBC的模板类时,需要传入数据源,这样JDBC的模板类才知道连接哪个数据库

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/475156.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot实战:打造企业资产管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

十大经典排序算法之一--------------堆排序(java详解)

一.堆排序基本介绍&#xff1a; 堆排序是利用堆这种数据结构而设计的一种排序算法&#xff0c;堆排序是一种选择排序&#xff0c;它的最坏&#xff0c;最好&#xff0c;平均时间复杂度均为O(nlogn)&#xff0c;它也是不稳定排序。堆是具有以下性质的完全二叉树&#xff1a;每个…

提升企业竞争力:精益生产培训简介——张驰咨询

精益生产&#xff08;Lean Production&#xff09;是一种管理哲学&#xff0c;最早源于日本丰田汽车公司的丰田生产系统&#xff08;Toyota Production System,TPS&#xff09;。这套理念的核心在于最大程度地减少生产过程中的浪费&#xff0c;同时保证产品质量&#xff0c;通过…

【STM32】软件SPI读写W25Q64芯片

目录 W25Q64模块 W25Q64芯片简介 硬件电路 W25Q64框图 Flash操作注意事项 状态寄存器 ​编辑 指令集 INSTRUCTIONS​编辑 ​编辑 SPI读写W25Q64代码 硬件接线图 MySPI.c MySPI.h W25Q64 W25Q64.c W25Q64.h main.c 测试 SPI通信&#xff08;W25Q64芯片简介&am…

机器学习---学习与推断,近似推断、话题模型

1. 学习与推断 基于概率图模型定义的分布&#xff0c;能对目标变量的边际分布&#xff08;marginal distribution&#xff09;或某些可观测变量 为条件的条件分布进行推断。对概率图模型&#xff0c;还需确定具体分布的参数&#xff0c;称为参数估计或学习问 题&#xff0c;…

生成式 AI - Diffusion 模型的数学原理(3)

来自 论文《 Denoising Diffusion Probabilistic Model》&#xff08;DDPM&#xff09; 论文链接&#xff1a; https://arxiv.org/abs/2006.11239 Hung-yi Lee 课件整理 文章目录 一、图像生成模型本质上的共同目标二、最大似然估计三、和VAE的关联四、概率计算 一、图像生成模…

蓝牙耳机哪个品牌质量最好最耐用?蓝牙耳机排行榜前十名分享

​在通勤途中&#xff0c;许多人喜欢通过听音乐来打发时间。如今&#xff0c;无线蓝牙耳机已经取代了有线耳机&#xff0c;让人们摆脱了线缆的束缚。然而&#xff0c;面对市场上众多的蓝牙耳机&#xff0c;许多人仍然不知道该如何选择。我整理出了几款还不错的蓝牙耳机&#xf…

【HarmonyOS】鸿蒙开发之Image组件——第3.1章

图片的放缩类型 Cover&#xff08;默认值&#xff09;&#xff1a;保持图片宽高比进行放缩显示&#xff0c;使得图片完全显示在显示边界外。 Image("https://seopic.699pic.com/photo/50110/8335.jpg_wh1200.jpg").width(100).margin({right:10}).objectFit(ImageFi…

78MXX——线性稳压器电路,用于各种电视机、收录机、电子仪器、设备的稳压电源上,内置短路保护电路,热保护电路

78MXX系列是用于各种电视机、收录机、电子仪器、设备的稳压电源电路。包括78M05、78M06、 78M08、 78M09、 78M10、 78M12、 78M15。 主要特点&#xff1a; ● 极限输出电流: 0.5A ● 固定输出电压: 5V、6V、8V、9V、10V、 12V、 15V ● 内置短路保护电路 ● 内置热保护电路 ●…

今日Arxiv最热大模型论文:大语言模型真的理解上下文了吗?新研究揭示惊人发现

探索大型语言模型的上下文理解能力 在自然语言处理&#xff08; Natural Language Processing,NLP&#xff09;领域&#xff0c;理解上下文是把握人类语言的关键。近年来&#xff0c;大语言模型&#xff08;LLMs&#xff09;在展示对语言的理解方面取得了令人瞩目的成就。然而…

Instagram 账号被封如何申诉?ins账号解封经验分享

不知道各位在玩转海外社媒平台时有没有遇到过Instagram账号异常的情况&#xff0c;比如会出现账号受限、帖子发不出去、账号被封号等情况?Instagram账号如果被封不用马上弃用&#xff0c;我们可以先尝试一下申诉&#xff0c;看看能不能把账号解封。所以今天将会出一篇Instagra…

涌现出来的模拟能力#OpenAI视频生成大模型构建世界模拟器的可行性

Q&#xff1a;Sora出来后&#xff0c;普通人应该怎么办&#xff1f; "Sora的到来带来了机遇和挑战。普通人关注创意和技术&#xff0c;探索表达想法的新方式。&#x1f31f;&#x1f52c;他们制作高质量视频&#xff0c;平衡工作与生活&#xff0c;并拥抱行业变革。梦想成…