👉 项目地址:GitHub - cynthiaCh/design-patterns-ts
本文是《TS手写设计模式》系列的第二篇,我们将一起手写实现 7个结构型设计模式,并结合 DSL 系统与中后台场景讲解落地思路。
结构型模式关注“如何优雅地组合类与对象”,适合构建 灵活、可扩展、易维护的系统骨架。
🧠 什么是结构型模式?
结构型模式解决的是:
✅ 如何组织多个类、对象之间的关系,从而实现系统功能的组合复用与灵活切换。
在前端实践中,它们广泛应用于:
- 表单渲染器、插件系统
- 老系统兼容、Schema 转换
- 复杂流程封装、事件处理增强
✅ 一、装饰器模式(Decorator Pattern)
不改变原有结构,为对象动态添加功能。
🎯 适用场景
- 字段增强(如加校验、只读、placeholder)
- 中间件式渲染增强(如高亮、调试日志)
✏️ TS 实现
interface Field {
render(): string
}
class InputField implements Field {
render() { return '<input />' }
}
class RequiredDecorator implements Field {
constructor(private field: Field) {}
render() {
return this.field.render() + ' *'
}
}
🧩 在 DSL 中怎么用?
给字段动态加功能,不污染原始类:
const baseField = new InputField()
const fieldWithRequired = new RequiredDecorator(baseField)
console.log(fieldWithRequired.render()) // <input /> *
支持组合多个装饰器,形成“插件链”!
✅ 二、适配器模式(Adapter Pattern)
兼容旧接口,让新代码复用旧逻辑。
🎯 适用场景
- 接入第三方 UI 库(如旧版 el-input)
- Schema 转换、组件兼容
✏️ TS 实现
interface NewField {
render(): string
}
class OldComponent {
show() { return 'old html' }
}
class FieldAdapter implements NewField {
constructor(private legacy: OldComponent) {}
render() {
return this.legacy.show()
}
}
🧩 在 DSL 中怎么用?
renderField(new FieldAdapter(new OldComponent()))
👉 在不重构旧组件的前提下,平滑接入到新版系统。
✅ 三、外观模式(Facade Pattern)
简化调用接口,隐藏系统复杂性。
🎯 适用场景
- 初始化流程封装(DSL 引擎启动器)
- 表单构造器/渲染器调用封装
✏️ TS 实现
class Compiler {
compile() {/*...*/} transform() {/*...*/} validate() {/*...*/}
}
class DSLFacade {
private compiler = new Compiler()
build() {
this.compiler.compile()
this.compiler.transform()
this.compiler.validate()
}
}
🧩 在 DSL 中怎么用?
const dsl = new DSLFacade()
dsl.build()
👉 外观模式让复杂逻辑只暴露一个简洁入口,用户无需关心底层细节,极大提升开发体验。
✅ 四、代理模式(Proxy Pattern)
控制对象访问,可添加权限/缓存/懒加载等逻辑。
应用示例:
class FieldProxy implements Field {
constructor(private realField: Field) {}
render() {
console.log('Log before render')
return this.realField.render()
}
}
👉 在 DSL 中常用于字段渲染日志、性能监控、权限校验。
✅ 五、组合模式(Composite Pattern)
将对象组合成树状结构,统一处理单个对象和组合对象。
应用示例:
interface Component { render(): string }
class FieldGroup implements Component {
constructor(private children: Component[]) {}
render() {
return this.children.map(c => c.render()).join('\n')
}
}
👉 表单分组、多字段嵌套的渲染器就是组合模式的最佳实践。
✅ 六、桥接模式(Bridge Pattern)
将抽象与实现分离,使它们可以独立变化。
应用示例:
interface Theme { getStyle(): string }
class DarkTheme implements Theme { getStyle() { return 'dark' } }
abstract class Field {
constructor(protected theme: Theme) {}
abstract render(): string
}
class SelectField extends Field {
render() { return `<select class="${this.theme.getStyle()}">...</select>` }
}
👉 用于主题系统、地域配置的样式与结构分离。
✅ 七、享元模式(Flyweight Pattern)
共享细粒度对象,降低内存使用。
应用示例:
class FieldFactory {
private static pool: Record<string, Field> = {}
static get(type: string): Field {
if (!this.pool[type]) {
this.pool[type] = new InputField()
}
return this.pool[type]
}
}
👉 在大规模字段动态渲染中减少重复对象创建,提升性能。
🧠 总结与对比
模式 | 关键词 | 典型用途 |
---|---|---|
装饰器 | 动态增强 | 字段插件、验证器、渲染增强 |
适配器 | 接口转换 | 接入旧组件/第三方 API |
外观 | 简化使用 | 系统初始化、表单构建 |
代理 | 访问控制 | 日志记录、懒加载、权限判断 |
组合 | 树形结构 | 字段组、嵌套布局 |
桥接 | 抽象分离 | 样式解耦、主题/地域切换 |
享元 | 对象复用 | 提高性能、内存优化 |
🚀 下一篇预告:行为型模式!
下一篇我们将进入「行为型模式」部分,包括:
- 策略模式(值处理策略)
- 观察者模式(事件系统)
- 责任链模式(校验链)
- 状态模式、命令模式、解释器模式……
📌 项目源码持续更新中 👉 GitHub
写给想深入理解系统设计的你!