Skip to main content

bridge

将抽象与实现分离,使二者可独立变化

Quellinformationen

Repository
microwind/ai-skills
Letzte Quellaktivität
31. März 2026 um 01:27
Erkannte Sprache von SKILL.md
Chinesisch
Sterne
83
Forks
24

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
4 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
Bridge
description
将抽象与实现分离,使二者可独立变化
license
MIT
# Bridge Pattern (桥接模式) ## 核心概念 **Bridge** 是一种**结构型设计模式**,用于将抽象与实现分离,使它们可以独立变化。 ### 关键原理 - 🔗 **分离关切** (Separation of Concerns) - 抽象与实现分开 - 📐 **维度分离** - 按不同维度定义类层级 - 🔄 **独立变化** - 抽象和实现都能独立扩展 - ✏️ **灵活组合** - 通过组合实现多维特性 ### 对比继承 | 继承 | 桥接 | |------|------| | Shape → Circle, Square | Shape + Renderer的组合 | | 类爆炸(M×N个类) | 只需M+N个类 | | 静态结构 | 动态灵活 | | 修改一维影响全部 | 维度独立变化 | ## 何时使用 1. **两个独立维度的变化** - Color × Shape、OS × Window、Device × Renderer 2. **避免类爆炸** - 用组合代替多重继承 3. **隐藏实现细节** - 客户端只见抽象 4. **运行时切换实现** - 动态决定使用哪个Implementor 5. **共享实现** - 多个Abstraction复用同一Implementor ## 基本结构 ### UML类图 ``` Abstraction Implementor △ △ │ │ ┌─────────┼─────────┐ ┌────────┴────────┐ │ │ │ │ │ RefinedAbstraction ConcreteImplementorA ConcreteImplementorB ``` ## 实现方式 ### 方法1: 虚方法模式 ```java // 实现接口 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(); ``` ### 方法2: 参数化桥接 ```java 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); } ``` ### 方法3: 配置驱动 ```java 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(); ``` ## 完美使用场景 ### 场景1: 跨平台UI - Window与OS适配 ```java // 抽象 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(); // 跨平台 ``` ### 场景2: 数据库访问 - 数据库方言 ```java 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"; } } ``` ### 场景3: 设备驱动 - 图形渲染 ```java 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(...); } } ``` ### 场景4: 支付系统 - 支付方式与支付渠道 ```java // 抽象维度:支付方式 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); } } ``` ### 场景5: 日志系统 - 日志级别与输出目标 ```java 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); } } ``` ### 场景6: 消息队列 - 消息格式与传输协议 ```java // 传输协议(实现维度) 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()); } } ``` ### 场景7: 主题(Pattern,配置系统 - UI主题与渲染引擎 ```java // 实现维度:渲染引擎 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()); } } ``` ### 场景8: 数据存储 - 数据格式与存储介质 ```java // 存储介质(实现维度) 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个类 ``` ### 分离的两个维度必须满足什么条件? 1. **独立变化** - 一个维度变化不影响另一个 ``` ✓ Shape和Color独立 → 分离 ✗ Button和ButtonListener不独立 → 不分离 ``` 2. **正交性** - 两个维度没有强依赖 ``` ✓ Window和OS是正交的 ✗ ListNode和DoubleLinkedListNode不正交 ``` 3. **各自可配置** - 都需要运行时决策 ``` ✓ Shape(Circle/Square) + Color(Red/Green) 都需要选择 ✗ Object和Class不需要同时选择 → 不用桥接 ``` ### 判断是否应该用桥接 ``` 是否有M×N的类爆炸? ├─ 是 → 考虑桥接 └─ 否 → 继承足够 两个维度独立变化? ├─ 是 → 进一步优化用桥接 └─ 否 → 继承更好 都需要运行时选择? ├─ 是 → 使用桥接✅ └─ 否 → 考虑其他 ``` --- ## 深入的常见问题解决 ### 问题1: 什么时候是"真正"的两个独立维度? **症状**: 分不清什么是真独立,什么是虚独立 **分析工具 - 变化频率矩阵**: ``` 维度组合 Shape变化频率 Renderer变化频率 ───────────────────────────────────────────────── Circle+GPU 每月1次 每周1次 ✅ 独立 Window+OS 每周1次 每月1次 ✅ 独立 Employee+Role 几乎不变 每年1次 ⚠️ 伪独立 Button+Color 经常 很少 ⚠️ 非对称 判断:如果两个维度的变化频率差异>5倍,或一个几乎不变 → 虚独立 → 不用桥接 ``` **错误示例**(伪独立): ```java // ❌ 不应该用桥接 public abstract class PaymentMethod { protected PaymentProcessor processor; // 伪桥接 } // 原因:PaymentMethod和Processor不独立 // Processor是PaymentMethod的依赖,不是平行维度 ``` **正确示例**(真独立): ```java // ✅ 真正的桥接 public abstract class Logger { protected LogOutput output; // 真桥接 } // 原因:Logger(级别)和Output(目标)互不依赖,独立变化 ``` ### 问题2: 抽象与实现应该如何划分? **规则**: ``` Abstraction: → 高层业务逻辑 → 稳定的部分 → 不经常变化 Implementor: → 低层技术细节 → 易变的部分 → 经常替换 ``` **判断标准 - 稳定性分析**: ```java // 分析:哪个更稳定? 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实现细节,不是业务抽象 } ``` ### 问题3: 如何动态切换Bridge的两端? **场景**: 运行时需要改变Implementor(如切换数据库) **方案1: Setter切换**(推荐简单场景) ```java 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: 工厂切换**(推荐复杂场景) ```java public class DialectFactory { private static Map<String, DatabaseDialect> dialects = new HashMap<>(); static { dialects.put("mysql", new MySQLDialect()); dialects.put("postgres", new PostgreSQLDialect());
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen