with one click
bridge
将抽象与实现分离,使二者可独立变化
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
将抽象与实现分离,使二者可独立变化
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| name | Bridge |
| description | 将抽象与实现分离,使二者可独立变化 |
| license | MIT |
Bridge 是一种结构型设计模式,用于将抽象与实现分离,使它们可以独立变化。
| 继承 | 桥接 |
|---|---|
| Shape → Circle, Square | Shape + Renderer的组合 |
| 类爆炸(M×N个类) | 只需M+N个类 |
| 静态结构 | 动态灵活 |
| 修改一维影响全部 | 维度独立变化 |
Abstraction Implementor
△ △
│ │
┌─────────┼─────────┐ ┌────────┴────────┐
│ │ │ │ │
RefinedAbstraction ConcreteImplementorA ConcreteImplementorB
// 实现接口
public interface Renderer {
void renderCircle();
}
// 实现者
public class PyramidRenderer implements Renderer {
@Override
public void renderCircle() {
System.out.println(" ^ ");
System.out.println(" / \ ");
}
}
// 抽象(包含对Implementor的引用)
public abstract class Shape {
protected Renderer renderer;
public Shape(Renderer renderer) {
this.renderer = renderer;
}
public abstract void draw();
}
// 精化抽象
public class Circle extends Shape {
@Override
public void draw() {
renderer.renderCircle();
}
}
// 使用
Renderer r = new PyramidRenderer();
Shape s = new Circle(r);
s.draw();
public abstract class AbstractShape {
private Map<String, Renderer> renderers;
public AbstractShape() {
this.renderers = new HashMap<>();
initializeRenderers();
}
protected abstract void initializeRenderers();
public void drawWith(String renderType) {
Renderer renderer = renderers.get(renderType);
if (renderer != null) {
performDraw(renderer);
}
}
protected abstract void performDraw(Renderer r);
}
public class BridgeFactory {
public static Shape create(String shapeType, String renderType) {
Renderer renderer = createRenderer(renderType);
return createShape(shapeType, renderer);
}
private static Renderer createRenderer(String type) {
// 从配置或工厂创建Renderer
return RendererFactory.create(type);
}
private static Shape createShape(String type, Renderer r) {
switch (type) {
case "circle": return new Circle(r);
case "square": return new Square(r);
default: throw new IllegalArgumentException(type);
}
}
}
// 使用
Shape shape = BridgeFactory.create("circle", "pyramid");
shape.draw();
// 抽象
public abstract class Window {
protected OS os;
public Window(OS os) { this.os = os; }
}
// 具体窗口
public class StandardWindow extends Window {
public void render() {
os.drawWindow("Standard");
}
}
// 实现者
public interface OS {
void drawWindow(String style);
}
// 具体平台
public class WindowsOS implements OS {
public void drawWindow(String style) {
System.out.println("Rendering on Windows: " + style);
}
}
// 使用
OS os = getOS(); // 运行时决定
Window win = new StandardWindow(os);
win.render(); // 跨平台
public abstract class DataMapper {
protected DatabaseDialect dialect;
}
public class UserMapper extends DataMapper {
public List<User> findAll() {
String sql = dialect.createSelectSQL("users");
return dialect.execute(sql);
}
}
// MySQL方言
public class MySQLDialect implements DatabaseDialect {
@Override
public String createSelectSQL(String table) {
return "SELECT * FROM " + table + " LIMIT 100";
}
}
// PostgreSQL方言
public class PostgreSQLDialect implements DatabaseDialect {
@Override
public String createSelectSQL(String table) {
return "SELECT * FROM " + table + " OFFSET 0 LIMIT 100";
}
}
public interface Renderer {
void renderPixel(int x, int y, Color color);
void drawLine(int x1, int y1, int x2, int y2);
}
public class GPURenderer implements Renderer {
public void renderPixel(int x, int y, Color color) {
// 调用GPU API
cuda.setPixel(x, y, color);
}
}
public abstract class Graphic {
protected Renderer renderer;
public abstract void draw();
}
public class Circle extends Graphic {
private int radius;
public void draw() {
// 使用renderer接口,独立于GPU/CPU
renderer.drawLine(...);
}
}
// 抽象维度:支付方式
public interface PaymentMethod {
double calculateFee(double amount);
boolean validate(String info);
}
// 实现维度:支付渠道
public interface PaymentChannel {
Receipt charge(double amount);
Receipt refund(String receiptId);
}
// 具体支付方式
public class CreditCard implements PaymentMethod {
public double calculateFee(double amount) {
return amount * 0.02; // 2%手续费
}
}
// 具体支付渠道
public class AlipayChannel implements PaymentChannel {
public Receipt charge(double amount) {
// 调用Alipay API
return alipayAPI.pay(amount);
}
}
// 桥接:支付处理
public abstract class PaymentProcessor {
protected PaymentMethod method;
protected PaymentChannel channel;
public Receipt processPayment(double amount) {
double fee = method.calculateFee(amount);
double total = amount + fee;
return channel.charge(total);
}
}
public interface LogOutput {
void write(String message);
void flush();
}
public class FileLogOutput implements LogOutput {
public void write(String message) {
fileWriter.println(message);
}
}
public abstract class Logger {
protected LogOutput output;
protected LogLevel level;
protected void log(String message) {
if (shouldLog()) {
output.write(formatMessage(message));
}
}
protected abstract String formatMessage(String message);
}
public class StructuredLogger extends Logger {
protected String formatMessage(String message) {
return String.format("[%s] %s", level, message);
}
}
// 传输协议(实现维度)
public interface Transport {
void send(Message msg);
Message receive();
void connect(String brokerUrl);
}
// 消息格式(抽象维度)
public abstract class Message {
protected Transport transport;
abstract byte[] serialize();
}
// JSON消息
public class JSONMessage extends Message {
byte[] serialize() {
return gson.toJson(this).getBytes();
}
}
// TCP传输
public class TCPTransport implements Transport {
public void send(Message msg) {
byte[] data = msg.serialize();
socket.send(data);
}
}
// AMQP传输
public class AMQPTransport implements Transport {
public void send(Message msg) {
channel.basicPublish(msg.serialize());
}
}
// 实现维度:渲染引擎
public interface RenderEngine {
void drawButton(Theme theme, String label);
void drawWindow(Theme theme, String title);
}
// 抽象维度:UI主题
public abstract class UITheme {
protected RenderEngine engine;
abstract void applyColors();
public void renderUI() {
applyColors();
engine.drawWindow(this, "Main");
engine.drawButton(this, "OK");
}
}
// 浅色主题
public class LightTheme extends UITheme {
void applyColors() {
backgroundColor = Color.WHITE;
textColor = Color.BLACK;
}
}
// SWT渲染
public class SWTEngine implements RenderEngine {
public void drawButton(UITheme theme, String label) {
button = new Button(shell, SWT.PUSH);
button.setText(label);
button.setBackground(theme.getBackgroundColor());
}
}
// Swing渲染
public class SwingEngine implements RenderEngine {
public void drawButton(UITheme theme, String label) {
JButton btn = new JButton(label);
btn.setBackground(theme.getBackgroundColor());
}
}
// 存储介质(实现维度)
public interface Storage {
void save(byte[] data);
byte[] load();
}
// 数据格式(抽象维度)
public abstract class DataStore {
protected Storage storage;
abstract byte[] encode();
abstract Object decode(byte[] data);
public void persist(Object obj) {
byte[] encoded = encode(obj);
storage.save(encoded);
}
}
// CSV格式
public class CSVDataStore extends DataStore {
byte[] encode(Object obj) {
return CSV.serialize(obj);
}
}
// 文件存储
public class FileStorage implements Storage {
public void save(byte[] data) {
FileOutputStream.write(data);
}
}
// 云存储(AWS S3)
public class S3Storage implements Storage {
public void save(byte[] data) {
s3Client.putObject(bucketName, key, data);
}
}
桥接模式的本质是解决两个独立变化维度的类爆炸问题。
❌ 不用桥接:继承树爆炸
Shape
├── Circle
│ ├── CircleRed (Shape×Color的笛卡尔积)
│ ├── CircleGreen
│ └── CircleBlue
├── Square
│ ├── SquareRed
│ ├── SquareGreen
│ └── SquareBlue
└── Triangle
├── TriangleRed
├── TriangleGreen
└── TriangleBlue
# 总计: 3 Shape × 3 Color = 9个类
✅ 用桥接:矩阵分离
Shape: Circle, Square, Triangle (3个)
Color: Red, Green, Blue (3个)
# 总计: 3 + 3 = 6个类
# 组合: 3 × 3 = 9种对象,但只需6个类
独立变化 - 一个维度变化不影响另一个
✓ Shape和Color独立 → 分离
✗ Button和ButtonListener不独立 → 不分离
正交性 - 两个维度没有强依赖
✓ Window和OS是正交的
✗ ListNode和DoubleLinkedListNode不正交
各自可配置 - 都需要运行时决策
✓ Shape(Circle/Square) + Color(Red/Green) 都需要选择
✗ Object和Class不需要同时选择 → 不用桥接
是否有M×N的类爆炸?
├─ 是 → 考虑桥接
└─ 否 → 继承足够
两个维度独立变化?
├─ 是 → 进一步优化用桥接
└─ 否 → 继承更好
都需要运行时选择?
├─ 是 → 使用桥接✅
└─ 否 → 考虑其他
症状: 分不清什么是真独立,什么是虚独立
分析工具 - 变化频率矩阵:
维度组合 Shape变化频率 Renderer变化频率
─────────────────────────────────────────────────
Circle+GPU 每月1次 每周1次 ✅ 独立
Window+OS 每周1次 每月1次 ✅ 独立
Employee+Role 几乎不变 每年1次 ⚠️ 伪独立
Button+Color 经常 很少 ⚠️ 非对称
判断:如果两个维度的变化频率差异>5倍,或一个几乎不变 → 虚独立 → 不用桥接
错误示例(伪独立):
// ❌ 不应该用桥接
public abstract class PaymentMethod {
protected PaymentProcessor processor; // 伪桥接
}
// 原因:PaymentMethod和Processor不独立
// Processor是PaymentMethod的依赖,不是平行维度
正确示例(真独立):
// ✅ 真正的桥接
public abstract class Logger {
protected LogOutput output; // 真桥接
}
// 原因:Logger(级别)和Output(目标)互不依赖,独立变化
规则:
Abstraction:
→ 高层业务逻辑
→ 稳定的部分
→ 不经常变化
Implementor:
→ 低层技术细节
→ 易变的部分
→ 经常替换
判断标准 - 稳定性分析:
// 分析:哪个更稳定?
Logger logger = new Logger("FILE", LogLevel.DEBUG); // 稳定
// vs
FileWriter fw = new FileWriter("/path/to/file.log"); // 易变
// Logger(抽象): 业务需要的日志级别 → 稳定
// FileWriter(实现): 具体输出目标 → 易变
// → Logger是Abstraction, FileWriter是Implementor ✅
// 反例:混淆了
public class Logger {
protected Renderer renderer; // 反了!
// Logger实现细节,不是业务抽象
}
场景: 运行时需要改变Implementor(如切换数据库)
方案1: Setter切换(推荐简单场景)
public class DataService {
private DatabaseDialect dialect;
public void setDialect(DatabaseDialect d) {
this.dialect = d;
}
public List<User> getUsers() {
return dialect.query("SELECT * FROM users");
}
}
// 使用
DataService service = new DataService();
service.setDialect(new MySQLDialect());
service.getUsers();
// 切换
service.setDialect(new PostgreSQLDialect());
service.getUsers(); // 同一个service,不同backend
方案2: 工厂切换(推荐复杂场景)
public class DialectFactory {
private static Map<String, DatabaseDialect> dialects = new HashMap<>();
static {
dialects.put("mysql", new MySQLDialect());
dialects.put("postgres", new PostgreSQLDialect());
dialects.put("oracle", new OracleDialect());
}
public static DatabaseDialect getDialect(String dbType) {
return dialects.get(dbType);
}
}
// 使用:从配置读取
DatabaseDialect dialect = DialectFactory.getDialect(config.getDbType());
DataService service = new DataService(dialect);
方案3: 策略切换(推荐高频切换)
public class AdaptiveService {
private Map<String, DatabaseDialect> dialects;
private DatabaseDialect current;
public void executeWithBestDialect(Query q) {
// 分析Query特征,选择最优Implementor
DatabaseDialect best = selectBest(q);
// 切换
this.current = best;
current.execute(q);
}
private DatabaseDialect selectBest(Query q) {
if (q.isSimple()) return dialects.get("sqlite");
if (q.isComplex()) return dialects.get("postgres");
return dialects.get("mysql");
}
}
症状: Abstraction引用Implementor,Implementor又需要Abstraction
反面示例(循环):
// ❌ 循环依赖
public abstract class Shape {
protected Renderer renderer;
public void render() {
renderer.render(this); // Shape传给Renderer
}
}
public interface Renderer {
void render(Shape shape); // Renderer依赖Shape
}
// 问题:Shape和Renderer相互依赖
正确示例(单向依赖):
// ✅ 单向依赖:Shape→Renderer
public abstract class Shape {
protected Renderer renderer;
public void render() {
Color c = getColor();
Size s = getSize();
renderer.render(c, s); // 只传递必要数据,不传Shape
}
}
public interface Renderer {
void render(Color color, Size size); // 无需知道Shape
}
// 场景:同时有Shape、Color、Renderer三个维度
public abstract class Shape {
protected ColorRenderer colorRenderer;
protected GeometryRenderer geometryRenderer;
public void render() {
geometryRenderer.render(this);
colorRenderer.render(this);
}
}
// 或者用组合模式
public class MultiDimensionalBridge {
private Map<String, Renderer> renderers = new HashMap<>();
public void register(String dimension, Renderer renderer) {
renderers.put(dimension, renderer);
}
public void render(Shape shape) {
renderers.values().forEach(r -> r.render(shape));
}
}
public class DynamicBridge {
private Object implementor;
private Class<?> implementorInterface;
public DynamicBridge(Object impl, Class<?> iface) {
this.implementor = impl;
this.implementorInterface = iface;
}
public Object invoke(String methodName, Object... args) {
return MethodHandle.from(implementor, methodName)
.invokeWithArguments(args);
}
}
// 使用
DynamicBridge bridge = new DynamicBridge(
new MySQLDialect(),
DatabaseDialect.class
);
bridge.invoke("query", sqlStatement); // 动态调用
| 模式 | 区别 | 何时结合 |
|---|---|---|
| Adapter | Adapter修补不兼容;Bridge分离设计 | 先用Bridge设计,Adapter处理遗留系统 |
| Strategy | Strategy处理算法选择;Bridge分离维度 | Bridge用于类层次,Strategy用于运行时选择 |
| Composite | Composite处理树结构;Bridge分离维度 | 多维树可同时用:Bridge分离Color,Composite管理父子 |
| Factory | Factory创建对象;Bridge分离实现 | 结合使用:BridgeFactory创建合适的Abstraction-Implementor对 |
| Decorator | Decorator逐层增强;Bridge分离实现 | 可结合:Decorator在Abstraction层做装饰 |
以聚合根为边界,包含多个相关Entity和ValueObject的集合。保证数据一致性和事务边界。
在DDD中具有唯一身份标识和生命周期的对象,通过身份而非属性值相等判断。
封装复杂对象和聚合的创建过程,将创建职责从领域对象中剥离,保证聚合创建时的不变量满足。
没有身份标识,通过属性值判断相等的对象。不可变,通常代表领域中的度量或描述。
命令查询责任分离,将数据的写入操作和读取操作分别用不同的模型处理,优化各自的性能。
将DDD战略设计应用于微服务架构,限界上下文指导服务拆分,领域事件实现服务间通信。