系列导读:在学习了接口适配后,我们来看如何处理抽象与实现的分离问题。桥接模式解决的是"多维度变化"的设计难题。
解决什么问题:将抽象部分与实现部分分离,使它们都可以独立变化。避免在多个维度上变化时出现类爆炸问题。
想象一下,你要设计一个图形绘制系统,既要支持不同的形状(圆形、矩形),又要支持不同的绘制方式(Windows绘制、Linux绘制)。如果用继承,你需要WindowsCircle、LinuxCircle、WindowsRectangle、LinuxRectangle等类,随着形状和平台的增加,类的数量会爆炸式增长。
桥接模式通过将"形状"和"绘制方式"分离成两个独立的层次结构,用组合代替继承,让两个维度可以独立变化和扩展。
本文在系列中的位置:
桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立变化。这种模式通过组合的方式,而不是继承的方式,来实现抽象和实现的解耦。桥接模式常用于需要多维度扩展的系统,能够有效避免类爆炸问题。
桥接模式将抽象部分与实现部分分离,使它们都可以独立地变化。通过在抽象层中持有实现层的引用,实现抽象和实现的解耦,便于系统的扩展和维护。
桥接模式适用于以下场景:
抽象和实现分离
多维度变化
运行时绑定
真实业务背景举例:
- 跨平台UI库,既要支持多种控件类型(如按钮、文本框),又要支持多种操作系统(如Windows、Linux、Mac),通过桥接模式实现控件与平台的解耦。
- 图形绘制系统,既要支持多种图形(如圆形、矩形),又要支持多种绘图API(如OpenGL、DirectX),通过桥接模式灵活组合。
- 云存储平台支持多种存储后端(如本地磁盘、阿里云OSS、亚马逊S3),通过桥接模式灵活切换存储实现。
@startuml
package "Bridge Pattern" #DDDDDD {
interface DrawingAPI {
+ drawCircle(x: int, y: int, radius: int): void
+ drawRectangle(x: int, y: int, width: int, height: int): void
}
class WindowsDrawingAPI implements DrawingAPI
class LinuxDrawingAPI implements DrawingAPI
abstract class Shape {
# drawingAPI: DrawingAPI
+ draw(): void
}
class Circle extends Shape
class Rectangle extends Shape
DrawingAPI <|.. WindowsDrawingAPI
DrawingAPI <|.. LinuxDrawingAPI
Shape <|-- Circle
Shape <|-- Rectangle
Shape o-- DrawingAPI : drawingAPI
}
@enduml
业务背景: 实现抽象与实现分离的基本结构,支持运行时切换实现。
package com.example.patterns.bridge;
import java.util.Objects;
// 实现接口,定义实现层的操作
public interface Implementor {
/**
* 实现层的具体操作
* 业务含义:底层平台或品牌的具体实现
*/
void operationImpl();
/**
* 获取实现类型
*/
String getType();
}
// 具体实现A,实现Implementor接口
public class ConcreteImplementorA implements Implementor {
@Override
public void operationImpl() {
try {
// 具体实现A的业务逻辑
System.out.println("ConcreteImplementorA operation - 执行实现A的业务逻辑");
} catch (Exception e) {
System.err.println("ImplementorA operation failed: " + e.getMessage());
throw new RuntimeException("实现A操作失败", e);
}
}
@Override
public String getType() {
return "ImplementorA";
}
}
// 具体实现B,实现Implementor接口
public class ConcreteImplementorB implements Implementor {
@Override
public void operationImpl() {
try {
// 具体实现B的业务逻辑
System.out.println("ConcreteImplementorB operation - 执行实现B的业务逻辑");
} catch (Exception e) {
System.err.println("ImplementorB operation failed: " + e.getMessage());
throw new RuntimeException("实现B操作失败", e);
}
}
@Override
public String getType() {
return "ImplementorB";
}
}
// 抽象类,持有实现接口的引用
public abstract class Abstraction {
protected final Implementor implementor;
/**
* 构造方法注入实现层,便于运行时切换
*/
public Abstraction(Implementor implementor) {
this.implementor = Objects.requireNonNull(implementor, "Implementor cannot be null");
}
/**
* 抽象层的操作,由子类实现
* 业务含义:对外暴露的统一接口
*/
public abstract void operation();
/**
* 获取当前实现类型
*/
public String getImplementorType() {
return implementor.getType();
}
}
// 扩展抽象类,实现具体的业务操作
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
@Override
public void operation() {
try {
// 调用实现层的操作,实现桥接
System.out.println("RefinedAbstraction: 准备调用实现层");
implementor.operationImpl();
System.out.println("RefinedAbstraction: 完成调用实现层");
} catch (Exception e) {
System.err.println("Abstraction operation failed: " + e.getMessage());
throw new RuntimeException("抽象层操作失败", e);
}
}
}
业务背景: 企业级消息推送系统需要支持多种消息类型(短信、邮件、推送通知)和多种推送平台(阿里云、腾讯云、华为云),通过桥接模式实现消息类型与推送平台的解耦。
package com.example.patterns.bridge.message;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.time.LocalDateTime;
// 推送平台接口
public interface MessagePlatform {
/**
* 发送消息
* @param recipient 接收者
* @param content 消息内容
* @param metadata 元数据
* @return 推送结果
*/
PushResult sendMessage(String recipient, String content, Map<String, Object> metadata);
/**
* 获取平台名称
*/
String getPlatformName();
/**
* 检查平台状态
*/
boolean isAvailable();
}
// 推送结果封装
public class PushResult {
private boolean success;
private String messageId;
private String platformName;
private String errorMessage;
private LocalDateTime timestamp;
public PushResult(boolean success, String messageId, String platformName, String errorMessage) {
this.success = success;
this.messageId = messageId;
this.platformName = platformName;
this.errorMessage = errorMessage;
this.timestamp = LocalDateTime.now();
}
// Getter方法
public boolean isSuccess() { return success; }
public String getMessageId() { return messageId; }
public String getPlatformName() { return platformName; }
public String getErrorMessage() { return errorMessage; }
public LocalDateTime getTimestamp() { return timestamp; }
@Override
public String toString() {
return String.format("PushResult{success=%s, messageId='%s', platform='%s', error='%s', time=%s}",
success, messageId, platformName, errorMessage, timestamp);
}
}
// 阿里云推送平台实现
public class AliyunMessagePlatform implements MessagePlatform {
private boolean available = true;
@Override
public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
try {
if (!isAvailable()) {
return new PushResult(false, null, getPlatformName(), "阿里云平台暂不可用");
}
// 模拟阿里云推送逻辑
String messageId = "aliyun_" + System.currentTimeMillis();
System.out.println("阿里云推送: 发送到 " + recipient + ", 内容: " + content);
return new PushResult(true, messageId, getPlatformName(), null);
} catch (Exception e) {
return new PushResult(false, null, getPlatformName(), "阿里云推送异常: " + e.getMessage());
}
}
@Override
public String getPlatformName() {
return "阿里云";
}
@Override
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
}
// 腾讯云推送平台实现
public class TencentMessagePlatform implements MessagePlatform {
private boolean available = true;
@Override
public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
try {
if (!isAvailable()) {
return new PushResult(false, null, getPlatformName(), "腾讯云平台暂不可用");
}
// 模拟腾讯云推送逻辑
String messageId = "tencent_" + System.currentTimeMillis();
System.out.println("腾讯云推送: 发送到 " + recipient + ", 内容: " + content);
return new PushResult(true, messageId, getPlatformName(), null);
} catch (Exception e) {
return new PushResult(false, null, getPlatformName(), "腾讯云推送异常: " + e.getMessage());
}
}
@Override
public String getPlatformName() {
return "腾讯云";
}
@Override
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
}
// 华为云推送平台实现
public class HuaweiMessagePlatform implements MessagePlatform {
private boolean available = true;
@Override
public PushResult sendMessage(String recipient, String content, Map<String, Object> metadata) {
try {
if (!isAvailable()) {
return new PushResult(false, null, getPlatformName(), "华为云平台暂不可用");
}
// 模拟华为云推送逻辑
String messageId = "huawei_" + System.currentTimeMillis();
System.out.println("华为云推送: 发送到 " + recipient + ", 内容: " + content);
return new PushResult(true, messageId, getPlatformName(), null);
} catch (Exception e) {
return new PushResult(false, null, getPlatformName(), "华为云推送异常: " + e.getMessage());
}
}
@Override
public String getPlatformName() {
return "华为云";
}
@Override
public boolean isAvailable() {
return available;
}
public void setAvailable(boolean available) {
this.available = available;
}
}
// 消息抽象类
public abstract class Message {
protected final MessagePlatform platform;
protected String title;
protected String content;
protected List<String> recipients;
protected Map<String, Object> metadata;
public Message(MessagePlatform platform) {
this.platform = Objects.requireNonNull(platform, "MessagePlatform cannot be null");
this.recipients = new ArrayList<>();
this.metadata = new HashMap<>();
}
public Message setTitle(String title) {
this.title = title;
return this;
}
public Message setContent(String content) {
this.content = content;
return this;
}
public Message addRecipient(String recipient) {
if (recipient != null && !recipient.trim().isEmpty()) {
this.recipients.add(recipient);
}
return this;
}
public Message addMetadata(String key, Object value) {
this.metadata.put(key, value);
return this;
}
/**
* 发送消息的抽象方法,由子类实现
*/
public abstract List<PushResult> send();
/**
* 格式化消息内容,由子类实现
*/
protected abstract String formatContent();
}
// 短信消息实现
public class SmsMessage extends Message {
public SmsMessage(MessagePlatform platform) {
super(platform);
}
@Override
public List<PushResult> send() {
List<PushResult> results = new ArrayList<>();
String formattedContent = formatContent();
for (String recipient : recipients) {
try {
PushResult result = platform.sendMessage(recipient, formattedContent, metadata);
results.add(result);
} catch (Exception e) {
PushResult errorResult = new PushResult(false, null, platform.getPlatformName(),
"发送短信异常: " + e.getMessage());
results.add(errorResult);
}
}
return results;
}
@Override
protected String formatContent() {
return "【短信通知】" + (title != null ? title + ": " : "") + content;
}
}
// 邮件消息实现
public class EmailMessage extends Message {
public EmailMessage(MessagePlatform platform) {
super(platform);
}
@Override
public List<PushResult> send() {
List<PushResult> results = new ArrayList<>();
String formattedContent = formatContent();
for (String recipient : recipients) {
try {
// 邮件特有的元数据
Map<String, Object> emailMetadata = new HashMap<>(metadata);
emailMetadata.put("subject", title);
emailMetadata.put("type", "email");
PushResult result = platform.sendMessage(recipient, formattedContent, emailMetadata);
results.add(result);
} catch (Exception e) {
PushResult errorResult = new PushResult(false, null, platform.getPlatformName(),
"发送邮件异常: " + e.getMessage());
results.add(errorResult);
}
}
return results;
}
@Override
protected String formatContent() {
StringBuilder html = new StringBuilder();
html.append("");
if (title != null) {
html.append(""
).append(title).append("");
}
html.append(""
).append(content).append("");
html.append("");
return html.toString();
}
}
// 推送通知消息实现
public class PushNotification extends Message {
public PushNotification(MessagePlatform platform) {
super(platform);
}
@Override
public List<PushResult> send() {
List<PushResult> results = new ArrayList<>();
String formattedContent = formatContent();
for (String recipient : recipients) {
try {
// 推送通知特有的元数据
Map<String, Object> pushMetadata = new HashMap<>(metadata);
pushMetadata.put("title", title);
pushMetadata.put("type", "push");
pushMetadata.put("badge", 1);
PushResult result = platform.sendMessage(recipient, formattedContent, pushMetadata);
results.add(result);
} catch (Exception e) {
PushResult errorResult = new PushResult(false, null, platform.getPlatformName(),
"发送推送通知异常: " + e.getMessage());
results.add(errorResult);
}
}
return results;
}
@Override
protected String formatContent() {
return content;
}
}
// 消息工厂
public class MessageFactory {
public static Message createSmsMessage(MessagePlatform platform) {
return new SmsMessage(platform);
}
public static Message createEmailMessage(MessagePlatform platform) {
return new EmailMessage(platform);
}
public static Message createPushNotification(MessagePlatform platform) {
return new PushNotification(platform);
}
}
// 平台工厂
public class PlatformFactory {
public static MessagePlatform createAliyunPlatform() {
return new AliyunMessagePlatform();
}
public static MessagePlatform createTencentPlatform() {
return new TencentMessagePlatform();
}
public static MessagePlatform createHuaweiPlatform() {
return new HuaweiMessagePlatform();
}
}
业务背景: 跨平台绘图系统,支持多种形状和多种绘图API的组合。
package com.example.patterns.bridge.graphics;
import java.awt.Color;
// 绘图API接口
public interface DrawingAPI {
void drawCircle(double x, double y, double radius, Color color);
void drawRectangle(double x, double y, double width, double height, Color color);
void drawLine(double x1, double y1, double x2, double y2, Color color);
String getApiName();
}
// Windows绘图API实现
public class WindowsDrawingAPI implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius, Color color) {
System.out.printf("Windows API: 绘制圆形 at (%.1f,%.1f) radius=%.1f color=%s%n",
x, y, radius, color.toString());
}
@Override
public void drawRectangle(double x, double y, double width, double height, Color color) {
System.out.printf("Windows API: 绘制矩形 at (%.1f,%.1f) size=%.1fx%.1f color=%s%n",
x, y, width, height, color.toString());
}
@Override
public void drawLine(double x1, double y1, double x2, double y2, Color color) {
System.out.printf("Windows API: 绘制直线 from (%.1f,%.1f) to (%.1f,%.1f) color=%s%n",
x1, y1, x2, y2, color.toString());
}
@Override
public String getApiName() {
return "Windows GDI";
}
}
// Linux绘图API实现
public class LinuxDrawingAPI implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius, Color color) {
System.out.printf("Linux X11: 绘制圆形 at (%.1f,%.1f) radius=%.1f color=%s%n",
x, y, radius, color.toString());
}
@Override
public void drawRectangle(double x, double y, double width, double height, Color color) {
System.out.printf("Linux X11: 绘制矩形 at (%.1f,%.1f) size=%.1fx%.1f color=%s%n",
x, y, width, height, color.toString());
}
@Override
public void drawLine(double x1, double y1, double x2, double y2, Color color) {
System.out.printf("Linux X11: 绘制直线 from (%.1f,%.1f) to (%.1f,%.1f) color=%s%n",
x1, y1, x2, y2, color.toString());
}
@Override
public String getApiName() {
return "Linux X11";
}
}
// 形状抽象类
public abstract class Shape {
protected final DrawingAPI drawingAPI;
protected double x, y;
protected Color color;
public Shape(DrawingAPI drawingAPI, double x, double y, Color color) {
this.drawingAPI = Objects.requireNonNull(drawingAPI, "DrawingAPI cannot be null");
this.x = x;
this.y = y;
this.color = color != null ? color : Color.BLACK;
}
public abstract void draw();
public abstract double getArea();
public void move(double deltaX, double deltaY) {
this.x += deltaX;
this.y += deltaY;
}
public void setColor(Color color) {
this.color = color != null ? color : Color.BLACK;
}
public String getApiName() {
return drawingAPI.getApiName();
}
}
// 圆形实现
public class Circle extends Shape {
private double radius;
public Circle(DrawingAPI drawingAPI, double x, double y, double radius, Color color) {
super(drawingAPI, x, y, color);
this.radius = Math.max(0, radius);
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius, color);
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
public void setRadius(double radius) {
this.radius = Math.max(0, radius);
}
public double getRadius() {
return radius;
}
}
// 矩形实现
public class Rectangle extends Shape {
private double width, height;
public Rectangle(DrawingAPI drawingAPI, double x, double y, double width, double height, Color color) {
super(drawingAPI, x, y, color);
this.width = Math.max(0, width);
this.height = Math.max(0, height);
}
@Override
public void draw() {
drawingAPI.drawRectangle(x, y, width, height, color);
}
@Override
public double getArea() {
return width * height;
}
public void setSize(double width, double height) {
this.width = Math.max(0, width);
this.height = Math.max(0, height);
}
public double getWidth() { return width; }
public double getHeight() { return height; }
}
// 客户端使用示例
public class BridgeClient {
public static void main(String[] args) {
// 消息推送系统示例
MessagePlatform aliyun = PlatformFactory.createAliyunPlatform();
Message smsMessage = MessageFactory.createSmsMessage(aliyun)
.setTitle("系统通知")
.setContent("您有一条新消息")
.addRecipient("13800138000")
.addRecipient("13900139000");
List<PushResult> results = smsMessage.send();
results.forEach(System.out::println);
// 绘图系统示例
DrawingAPI windowsAPI = new WindowsDrawingAPI();
DrawingAPI linuxAPI = new LinuxDrawingAPI();
Shape circle1 = new Circle(windowsAPI, 10, 10, 5, Color.RED);
Shape circle2 = new Circle(linuxAPI, 20, 20, 8, Color.BLUE);
System.out.println("绘制图形:");
circle1.draw();
circle2.draw();
System.out.printf("圆形1面积: %.2f (使用%s)%n", circle1.getArea(), circle1.getApiName());
System.out.printf("圆形2面积: %.2f (使用%s)%n", circle2.getArea(), circle2.getApiName());
}
// 总结:通过桥接模式,消息类型与推送平台、形状与绘图API实现了解耦,便于灵活扩展和组合。
}
业务背景: 验证桥接模式的核心功能,包括基本桥接功能、消息推送系统和绘图系统。
package com.example.patterns.bridge.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.*;
import java.awt.Color;
import java.util.List;
public class BridgePatternTest {
private MessagePlatform aliyunPlatform;
private MessagePlatform tencentPlatform;
private DrawingAPI windowsAPI;
private DrawingAPI linuxAPI;
@BeforeEach
public void setUp() {
aliyunPlatform = PlatformFactory.createAliyunPlatform();
tencentPlatform = PlatformFactory.createTencentPlatform();
windowsAPI = new WindowsDrawingAPI();
linuxAPI = new LinuxDrawingAPI();
}
@Test
public void testBasicBridgePattern() {
// 测试基本桥接模式
Implementor implA = new ConcreteImplementorA();
Implementor implB = new ConcreteImplementorB();
Abstraction abstractionA = new RefinedAbstraction(implA);
Abstraction abstractionB = new RefinedAbstraction(implB);
// 验证可以正常调用
assertDoesNotThrow(() -> {
abstractionA.operation();
abstractionB.operation();
});
// 验证实现类型正确
assertEquals("ImplementorA", abstractionA.getImplementorType());
assertEquals("ImplementorB", abstractionB.getImplementorType());
}
@Test
public void testAbstractionWithNullImplementor() {
// 测试空实现异常处理
assertThrows(NullPointerException.class, () -> {
new RefinedAbstraction(null);
});
}
@Test
public void testSmsMessageSending() {
// 测试短信消息发送
Message smsMessage = MessageFactory.createSmsMessage(aliyunPlatform)
.setTitle("测试通知")
.setContent("这是一条测试短信")
.addRecipient("13800138000")
.addRecipient("13900139000");
List<PushResult> results = smsMessage.send();
assertNotNull("发送结果不应为空", results);
assertEquals("应该有两条发送结果", 2, results.size());
for (PushResult result : results) {
assertTrue("发送应该成功", result.isSuccess());
assertEquals("平台应为阿里云", "阿里云", result.getPlatformName());
assertNotNull("消息ID不应为空", result.getMessageId());
assertTrue("消息ID应以aliyun开头", result.getMessageId().startsWith("aliyun_"));
}
}
@Test
public void testEmailMessageSending() {
// 测试邮件消息发送
Message emailMessage = MessageFactory.createEmailMessage(tencentPlatform)
.setTitle("重要通知")
.setContent("这是一封重要邮件")
.addRecipient("[email protected]")
.addMetadata("priority", "high");
List<PushResult> results = emailMessage.send();
assertNotNull("发送结果不应为空", results);
assertEquals("应该有一条发送结果", 1, results.size());
PushResult result = results.get(0);
assertTrue("发送应该成功", result.isSuccess());
assertEquals("平台应为腾讯云", "腾讯云", result.getPlatformName());
assertNotNull("时间戳不应为空", result.getTimestamp());
}
@Test
public void testPushNotificationSending() {
// 测试推送通知发送
MessagePlatform huaweiPlatform = PlatformFactory.createHuaweiPlatform();
Message pushMessage = MessageFactory.createPushNotification(huaweiPlatform)
.setTitle("系统更新")
.setContent("新版本已可用")
.addRecipient("user123")
.addMetadata("action", "update");
List<PushResult> results = pushMessage.send();
assertNotNull("发送结果不应为空", results);
assertEquals("应该有一条发送结果", 1, results.size());
PushResult result = results.get(0);
assertTrue("发送应该成功", result.isSuccess());
assertEquals("平台应为华为云", "华为云", result.getPlatformName());
assertTrue("消息ID应以huawei开头", result.getMessageId().startsWith("huawei_"));
}
@Test
public void testMessageWithUnavailablePlatform() {
// 测试平台不可用时的处理
AliyunMessagePlatform aliyun = new AliyunMessagePlatform();
aliyun.setAvailable(false);
Message smsMessage = MessageFactory.createSmsMessage(aliyun)
.setContent("测试消息")
.addRecipient("13800138000");
List<PushResult> results = smsMessage.send();
assertNotNull("发送结果不应为空", results);
assertEquals("应该有一条发送结果", 1, results.size());
PushResult result = results.get(0);
assertFalse("发送应该失败", result.isSuccess());
assertEquals("错误信息应正确", "阿里云平台暂不可用", result.getErrorMessage());
}
@Test
public void testMessageWithNullPlatform() {
// 测试空平台异常处理
assertThrows(NullPointerException.class, () -> {
MessageFactory.createSmsMessage(null);
});
}
@Test
public void testMessageBuilderPattern() {
// 测试消息构建器模式
Message message = MessageFactory.createSmsMessage(aliyunPlatform)
.setTitle("测试")
.setContent("内容")
.addRecipient("13800138000")
.addRecipient("") // 空接收者应被忽略
.addRecipient(null) // null接收者应被忽略
.addMetadata("key1", "value1")
.addMetadata("key2", "value2");
List<PushResult> results = message.send();
// 应该只有一条有效的接收者
assertEquals("应该只有一条发送结果", 1, results.size());
}
@Test
public void testCircleDrawing() {
// 测试圆形绘制
Shape circle1 = new Circle(windowsAPI, 10, 10, 5, Color.RED);
Shape circle2 = new Circle(linuxAPI, 20, 20, 8, Color.BLUE);
// 验证可以正常绘制
assertDoesNotThrow(() -> {
circle1.draw();
circle2.draw();
});
// 验证API名称
assertEquals("Windows GDI", circle1.getApiName());
assertEquals("Linux X11", circle2.getApiName());
// 验证面积计算
assertEquals(Math.PI * 25, circle1.getArea(), 0.001);
assertEquals(Math.PI * 64, circle2.getArea(), 0.001);
}
@Test
public void testRectangleDrawing() {
// 测试矩形绘制
Shape rect1 = new Rectangle(windowsAPI, 0, 0, 10, 20, Color.GREEN);
Shape rect2 = new Rectangle(linuxAPI, 5, 5, 15, 25, Color.YELLOW);
// 验证可以正常绘制
assertDoesNotThrow(() -> {
rect1.draw();
rect2.draw();
});
// 验证面积计算
assertEquals(200, rect1.getArea(), 0.001);
assertEquals(375, rect2.getArea(), 0.001);
}
@Test
public void testShapeWithNullAPI() {
// 测试空绘图API异常处理
assertThrows(NullPointerException.class, () -> {
new Circle(null, 0, 0, 5, Color.RED);
});
assertThrows(NullPointerException.class, () -> {
new Rectangle(null, 0, 0, 10, 20, Color.BLUE);
});
}
@Test
public void testShapeMovement() {
// 测试形状移动
Circle circle = new Circle(windowsAPI, 10, 10, 5, Color.RED);
circle.move(5, 3);
// 注意:这里我们无法直接验证移动结果,因为x,y是protected
// 在实际项目中,可以添加getter方法或测试绘制输出
assertDoesNotThrow(() -> circle.draw());
}
@Test
public void testShapeColorChange() {
// 测试形状颜色变更
Circle circle = new Circle(windowsAPI, 10, 10, 5, Color.RED);
circle.setColor(Color.BLUE);
circle.setColor(null); // 应设置为默认黑色
assertDoesNotThrow(() -> circle.draw());
}
@Test
public void testCircleRadiusValidation() {
// 测试圆形半径验证
Circle circle = new Circle(windowsAPI, 0, 0, -5, Color.RED);
// 负半径应被修正为0
assertEquals(0, circle.getRadius(), 0.001);
circle.setRadius(10);
assertEquals(10, circle.getRadius(), 0.001);
circle.setRadius(-3); // 应被修正为0
assertEquals(0, circle.getRadius(), 0.001);
}
@Test
public void testRectangleSizeValidation() {
// 测试矩形尺寸验证
Rectangle rect = new Rectangle(windowsAPI, 0, 0, -10, -20, Color.BLUE);
// 负尺寸应被修正为0
assertEquals(0, rect.getWidth(), 0.001);
assertEquals(0, rect.getHeight(), 0.001);
assertEquals(0, rect.getArea(), 0.001);
rect.setSize(15, 25);
assertEquals(15, rect.getWidth(), 0.001);
assertEquals(25, rect.getHeight(), 0.001);
assertEquals(375, rect.getArea(), 0.001);
}
@Test
public void testMessageFactoryCreation() {
// 测试消息工厂创建
Message sms = MessageFactory.createSmsMessage(aliyunPlatform);
Message email = MessageFactory.createEmailMessage(aliyunPlatform);
Message push = MessageFactory.createPushNotification(aliyunPlatform);
assertTrue("应创建短信消息", sms instanceof SmsMessage);
assertTrue("应创建邮件消息", email instanceof EmailMessage);
assertTrue("应创建推送通知", push instanceof PushNotification);
}
@Test
public void testPlatformFactoryCreation() {
// 测试平台工厂创建
MessagePlatform aliyun = PlatformFactory.createAliyunPlatform();
MessagePlatform tencent = PlatformFactory.createTencentPlatform();
MessagePlatform huawei = PlatformFactory.createHuaweiPlatform();
assertTrue("应创建阿里云平台", aliyun instanceof AliyunMessagePlatform);
assertTrue("应创建腾讯云平台", tencent instanceof TencentMessagePlatform);
assertTrue("应创建华为云平台", huawei instanceof HuaweiMessagePlatform);
assertEquals("阿里云", aliyun.getPlatformName());
assertEquals("腾讯云", tencent.getPlatformName());
assertEquals("华为云", huawei.getPlatformName());
}
@Test
public void testPushResultToString() {
// 测试推送结果字符串表示
PushResult result = new PushResult(true, "test123", "阿里云", null);
String resultString = result.toString();
assertNotNull("字符串表示不应为空", resultString);
assertTrue("应包含成功状态", resultString.contains("success=true"));
assertTrue("应包含消息ID", resultString.contains("messageId='test123'"));
assertTrue("应包含平台名称", resultString.contains("platform='阿里云'"));
}
}
误区1 :过度使用桥接模式
// 错误示例:为简单功能滥用桥接模式
public interface SimpleOperation {
void doSomething();
}
public class SimpleImplementation implements SimpleOperation {
public void doSomething() { System.out.println("简单操作"); }
}
// 不必要的抽象层
public abstract class UnnecessaryAbstraction {
protected SimpleOperation operation;
public UnnecessaryAbstraction(SimpleOperation operation) {
this.operation = operation;
}
public abstract void execute();
}
正确做法:只在真正需要多维度扩展时使用桥接模式。
误区2 :抽象与实现边界不清
// 错误示例:抽象层包含具体实现逻辑
public class BadAbstraction {
private Implementation impl;
public void operation() {
// 错误:在抽象层处理具体业务逻辑
validateInput();
logOperation();
impl.doWork();
updateDatabase();
}
}
正确做法:抽象层只做接口转换,具体逻辑放在实现层。
误区3 :忽略运行时切换的线程安全
// 错误示例:非线程安全的实现切换
public class UnsafeAbstraction {
private Implementation impl;
public void setImplementation(Implementation impl) {
this.impl = impl; // 可能导致并发问题
}
}
反例1 :硬编码实现选择
在抽象层中硬编码选择具体实现,失去了桥接模式的灵活性。
反例2 :实现层相互依赖
不同实现之间存在耦合,违反了桥接模式的解耦原则。
反例3 :抽象层过于复杂
抽象层包含过多业务逻辑,模糊了抽象与实现的边界。
清晰的职责分离 :明确抽象和实现的边界
// 推荐:清晰的职责分离
public abstract class PaymentProcessor {
protected final PaymentGateway gateway;
public PaymentProcessor(PaymentGateway gateway) {
this.gateway = Objects.requireNonNull(gateway);
}
// 抽象层负责流程控制
public final PaymentResult process(PaymentRequest request) {
validateRequest(request);
return doProcess(request);
}
protected abstract PaymentResult doProcess(PaymentRequest request);
protected abstract void validateRequest(PaymentRequest request);
}
接口设计要稳定 :实现接口应保持向后兼容
// 推荐:版本化接口设计
public interface PaymentGateway {
PaymentResult processPayment(PaymentRequest request);
// 扩展方法,保持向后兼容
default PaymentResult processPayment(PaymentRequest request, PaymentOptions options) {
return processPayment(request);
}
String getGatewayVersion();
}
使用工厂模式创建桥接 :简化客户端使用
// 推荐:桥接工厂
public class MessageBridgeFactory {
private static final Map<String, MessagePlatform> PLATFORMS = new ConcurrentHashMap<>();
static {
PLATFORMS.put("aliyun", new AliyunMessagePlatform());
PLATFORMS.put("tencent", new TencentMessagePlatform());
PLATFORMS.put("huawei", new HuaweiMessagePlatform());
}
public static Message createMessage(String type, String platform) {
MessagePlatform platformImpl = PLATFORMS.get(platform);
if (platformImpl == null) {
throw new IllegalArgumentException("Unsupported platform: " + platform);
}
return MessageFactory.createMessage(type, platformImpl);
}
}
支持运行时切换 :提供安全的实现切换机制
// 推荐:线程安全的实现切换
public class SwitchableProcessor {
private volatile Implementation impl;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public void switchImplementation(Implementation newImpl) {
lock.writeLock().lock();
try {
this.impl = Objects.requireNonNull(newImpl);
} finally {
lock.writeLock().unlock();
}
}
public void process() {
lock.readLock().lock();
try {
impl.doWork();
} finally {
lock.readLock().unlock();
}
}
}
配置化实现选择 :通过配置管理实现选择
// 推荐:配置化桥接
@Component
public class ConfigurableBridge {
@Value("${bridge.implementation.type:default}")
private String implementationType;
@Autowired
private Map<String, Implementation> implementations;
@PostConstruct
public void init() {
Implementation impl = implementations.get(implementationType);
if (impl == null) {
throw new IllegalStateException("No implementation found for type: " + implementationType);
}
setImplementation(impl);
}
}
缓存策略 :合理使用缓存提升性能
// 推荐:带缓存的桥接实现
public class CachedMessageBridge {
private final MessagePlatform platform;
private final Cache<String, MessageTemplate> templateCache;
public CachedMessageBridge(MessagePlatform platform) {
this.platform = platform;
this.templateCache = Caffeine.newBuilder()
.maximumSize(1000)
.expireAfterWrite(Duration.ofMinutes(30))
.build();
}
public PushResult sendTemplateMessage(String templateId, Map<String, Object> params) {
MessageTemplate template = templateCache.get(templateId,
key -> platform.getTemplate(key));
return platform.sendMessage(template.format(params));
}
}
异步处理 :支持异步操作提升吞吐量
// 推荐:异步桥接实现
public class AsyncMessageBridge {
private final MessagePlatform platform;
private final Executor executor;
public CompletableFuture<PushResult> sendMessageAsync(Message message) {
return CompletableFuture.supplyAsync(() -> {
try {
return platform.sendMessage(message);
} catch (Exception e) {
return new PushResult(false, null, platform.getPlatformName(), e.getMessage());
}
}, executor);
}
}
监控和日志 :完善的观察性支持
// 推荐:带监控的桥接实现
public class MonitoredBridge {
private static final Logger log = LoggerFactory.getLogger(MonitoredBridge.class);
private final MeterRegistry meterRegistry;
private final Implementation impl;
public void process(Request request) {
Timer.Sample sample = Timer.start(meterRegistry);
String implType = impl.getClass().getSimpleName();
try {
log.debug("Processing request with implementation: {}", implType);
impl.doWork(request);
meterRegistry.counter("bridge.success", "impl", implType).increment();
} catch (Exception e) {
log.error("Bridge processing failed with implementation: {}", implType, e);
meterRegistry.counter("bridge.error", "impl", implType).increment();
throw e;
} finally {
sample.stop(Timer.builder("bridge.duration")
.tag("impl", implType)
.register(meterRegistry));
}
}
}
扩展点设计 :提供灵活的扩展机制
// 推荐:可扩展的桥接设计
public abstract class ExtensibleBridge {
protected final List<BridgeInterceptor> interceptors = new ArrayList<>();
protected final Implementation impl;
public void addInterceptor(BridgeInterceptor interceptor) {
interceptors.add(interceptor);
}
protected final void process(Request request) {
// 前置处理
interceptors.forEach(i -> i.beforeProcess(request));
try {
doProcess(request);
// 后置处理
interceptors.forEach(i -> i.afterProcess(request));
} catch (Exception e) {
// 异常处理
interceptors.forEach(i -> i.onError(request, e));
throw e;
}
}
protected abstract void doProcess(Request request);
}
版本兼容性 :支持多版本实现共存
// 推荐:版本感知的桥接
public class VersionAwareBridge {
private final Map<String, Implementation> implementations;
public void process(Request request) {
String version = request.getVersion();
Implementation impl = implementations.get(version);
if (impl == null) {
// 降级到默认版本
impl = implementations.get("default");
}
if (impl == null) {
throw new UnsupportedOperationException("No implementation for version: " + version);
}
impl.process(request);
}
}
本文为设计模式系列第10篇,后续每篇将聚焦一个设计模式或设计原则,深入讲解实现与应用,敬请关注。