桥接模式(Bridge Pattern)是一种结构型设计模式,用于将抽象部分与其实现部分分离,使两者可以独立变化。
设计模式原理
桥接模式的核心思想是将抽象(节点逻辑)与实现(运行时环境)分离开来,通过组合而非继承实现两者之间的桥接。这样可以实现:
- 解耦性 :节点逻辑与运行时环境分离,各自独立变化。
- 灵活性 :支持多种节点类型与运行时环境的组合(如脚本节点在 Deno 或 Bun.js 中执行)。
- 封装性 :隐藏运行时环境的内部实现,客户端只需关注节点逻辑的使用。
在 TypeScript 中,桥接模式可以通过接口和组合实现,也可以通过泛型增强类型安全性。
桥接模式的结构
桥接模式通常包含以下几个角色:
- Abstraction(抽象类) :定义节点的高级接口,持有实现部分的引用。
- RefinedAbstraction(扩展抽象类) :实现具体的节点逻辑,如脚本节点。
- Implementor(实现接口) :定义运行时环境的接口,如执行脚本方法。
- ConcreteImplementor(具体实现类) :实现具体的运行时环境,如 DenoRuntime 或 BunRuntime。
优点
- 解耦性 :节点逻辑与运行时环境分离,降低耦合度。
- 可扩展性 :支持添加新节点类型或新运行时环境,只需实现新类。
- 类型安全 :TypeScript 的类型系统确保节点与环境的类型一致。
适用场景
- 需要将节点逻辑(如脚本执行)与运行时环境(如 Deno、Bun.js)解耦时。
- 需要支持多种节点类型与运行时环境的组合。
- 希望隐藏运行时环境的内部实现细节。
TypeScript 实现示例
以下是一个使用 TypeScript 实现桥接模式的示例。我们将创建一个工作流系统,支持 TypeScript 脚本节点(如用户验证脚本),并通过桥接模式在不同运行时环境(Deno 和 Bun.js)中执行。客户端通过 JSON 配置定义节点,桥接模式将节点逻辑与运行时实现分离。
typescript
// JSON 节点配置接口
interface NodeConfigJson {
nodeType: 'script';
runtime: 'deno' | 'bun';
params: {
id: string;
userId: string;
};
}
// 实现接口:运行时环境
interface RuntimeEnvironment {
executeScript(script: string, nodeId: string): string;
}
// 具体实现:Deno 运行时
class DenoRuntime implements RuntimeEnvironment {
executeScript(script: string, nodeId: string): string {
return `Deno 运行时(节点 ${nodeId}):执行脚本 "${script}",使用 Deno APIs,结果:已运行(Deno 1.45)。`;
}
}
// 具体实现:Bun.js 运行时
class BunRuntime implements RuntimeEnvironment {
executeScript(script: string, nodeId: string): string {
return `Bun.js 运行时(节点 ${nodeId}):执行脚本 "${script}",使用 Bun APIs,结果:已运行(Bun 1.1)。`;
}
}
// 抽象类:工作流节点
abstract class WorkflowNode {
protected environment: RuntimeEnvironment;
constructor(environment: RuntimeEnvironment) {
this.environment = environment;
}
abstract execute(nodeId: string): string;
abstract getDetails(): string;
}
// 扩展抽象类:脚本节点
class ScriptNode extends WorkflowNode {
private userId: string;
constructor(environment: RuntimeEnvironment, userId: string) {
super(environment);
this.userId = userId;
}
execute(nodeId: string): string {
const script = this.getScript();
return this.environment.executeScript(script, nodeId);
}
getDetails(): string {
return `详情:脚本节点,用户 ID=${this.userId}`;
}
private getScript(): string {
return `验证用户 ${this.userId} 的权限(TypeScript 脚本:if (user.permissions) { console.log('验证通过'); })`;
}
}
// 工作流引擎
class WorkflowEngine {
private runtimeMap: { [key: string]: new () => RuntimeEnvironment } = {
deno: DenoRuntime,
bun: BunRuntime
};
createNode(json: NodeConfigJson): WorkflowNode {
const RuntimeClass = this.runtimeMap[json.runtime];
if (!RuntimeClass) throw new Error(`不支持的运行时:${json.runtime}`);
const environment = new RuntimeClass();
return new ScriptNode(environment, json.params.userId);
}
}
// 客户端代码:处理 JSON 节点数组
function processWorkflow(engine: WorkflowEngine, nodes: NodeConfigJson[]) {
nodes.forEach((nodeConfig, index) => {
console.log(`处理节点 ${index + 1}(类型:${nodeConfig.nodeType},运行时:${nodeConfig.runtime}):`);
const node = engine.createNode(nodeConfig);
console.log(node.execute(nodeConfig.params.id));
console.log(node.getDetails());
console.log("");
});
}
// 测试代码
function main() {
const nodes: NodeConfigJson[] = [
{
nodeType: 'script',
runtime: 'deno',
params: { id: 'NODE001', userId: 'user123' }
},
{
nodeType: 'script',
runtime: 'bun',
params: { id: 'NODE002', userId: 'user456' }
}
];
console.log("工作流:执行 TypeScript 脚本节点");
const engine = new WorkflowEngine();
processWorkflow(engine, nodes);
}
main();
运行结果
运行以上代码,将输出:
ini
工作流:执行 TypeScript 脚本节点
处理节点 1(类型:script,运行时:deno):
Deno 运行时(节点 NODE001):执行脚本 "验证用户 user123 的权限(TypeScript 脚本:if (user.permissions) { console.log('验证通过'); })",使用 Deno APIs,结果:已运行(Deno 1.45)。
详情:脚本节点,用户 ID=user123
处理节点 2(类型:script,运行时:bun):
Bun.js 运行时(节点 NODE002):执行脚本 "验证用户 user456 的权限(TypeScript 脚本:if (user.permissions) { console.log('验证通过'); })",使用 Bun APIs,结果:已运行(Bun 1.1)。
详情:脚本节点,用户 ID=user456
总结
桥接模式通过分离节点逻辑与运行时环境,提供灵活的组件组合方式。TypeScript 的接口和组合机制为其提供了强大支持,而桥接模式进一步扩展到多环境场景,如 Node.js 的自定义桥接执行器示例。通过运行时桥接,脚本执行流清晰转换,实现了类似 Deno 脚本执行器的简洁 API。这展示了桥接模式在现代工作流开发中的强大应用。