桥接模式也称为桥梁模式、接口模式或者柄体(Handle and Body)模式,是将抽象部分与他的具体实现部分分离,使它们都可以独立地变化,通过组合的方式建立两个类之间的联系,而不是继承。
桥接模式是一种结构型设计模式,旨在将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过使用组合而不是继承的方式,可以更灵活地组织和管理代码。
结构:
优点:
缺点:
注意事项
适用场景
需求
假设我们正在开发一个电商平台,该平台需要发送不同类型的通知给用户,例如电子邮件通知、短信通知、App推送通知等。同时,用户可能也有不同的偏好和设备,例如有些用户更喜欢通过邮件接收通知,而另一些用户则更倾向于使用手机App接收通知。
实现思路
/**
* 通知接口
* @author 13723
* @version 1.0
* 2024/2/7 10:17
*/
public interface Notification {
/**
* 通知
* @param message 通知消息
*/
void notify(String message);
}
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 通知消息
*/
@Override
public void notify(String message) {
logger.error("【APP通知】: {}", message);
}
}
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 通知消息
*/
@Override
public void notify(String message) {
logger.error("【邮件通知】: {}", message);
}
}
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 通知消息
*/
@Override
public void notify(String message) {
logger.error("【邮件通知】: {}", message);
}
}
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;
}
}
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);
}
}
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);
}
}
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!");
}
}
@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 使用了以下几个关键角色:
JdbcTemplate
中,抽象部分代表了对数据库操作的抽象接口,例如 JdbcTemplate
类本身以及它的一些方法,如 query()
、update()
等。JdbcTemplate
中,实现部分代表了对底层数据库访问的实现,例如 DataSource
接口和各种数据库驱动实现。DriverManagerDataSource
、C3P0DataSource
等。// 在创建JDBC的模板类时,需要传入数据源,这样JDBC的模板类才知道连接哪个数据库