设计模式:23种经典模式在 TypeScript/Java 中的应用
软件设计模式(GoF)实战解析
引言:为什么你需要设计模式
在软件开发中,许多问题反复出现,优秀的设计模式正是对这些常见问题的标准解决方案。1994年,四人组(Gang of Four, GoF)在《设计模式:可复用面向对象软件的基础》一书中总结了23种经典设计模式,至今仍是面向对象设计的核心知识。
本教程将逐一解析这23种模式,并使用 TypeScript 与 Java 两种主流语言给出实战案例。无论你是前端还是后端开发者,都能从中获得可直接用于项目的设计思路。
设计模式的三大分类
| 分类 | 数量 | 核心思想 |
|---|---|---|
| 创建型模式 | 5种 | 将对象的创建与使用分离,提供更灵活的实例化方式 |
| 结构型模式 | 7种 | 通过组合类或对象形成更大的结构,同时保持结构的灵活和高效 |
| 行为型模式 | 11种 | 专注于对象间的通信和职责分配,让算法和交互更易复用和修改 |
接下来,我们按类别逐一突破。
一、创建型模式(5种)
1. 单例模式(Singleton)
意图:确保一个类只有一个实例,并提供全局访问点。
典型场景:配置管理、日志记录器、数据库连接池。
TypeScript 实现
class Singleton {
private static instance: Singleton;
private constructor() {}
public static getInstance(): Singleton {
if (!Singleton.instance) {
Singleton.instance = new Singleton();
}
return Singleton.instance;
}
public someMethod(): void {}
}
Java 实现(双重校验锁)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
2. 工厂方法模式(Factory Method)
意图:定义一个创建对象的接口,但让子类决定实例化哪个类。
典型场景:日志框架(文件日志、数据库日志)、跨平台 UI 组件。
TypeScript 实现
interface Product { operation(): string; }
class ConcreteProductA implements Product { operation() { return 'A'; } }
class ConcreteProductB implements Product { operation() { return 'B'; } }
abstract class Creator {
abstract factoryMethod(): Product;
someOperation() {
const product = this.factoryMethod();
return `Creator worked with ${product.operation()}`;
}
}
class ConcreteCreatorA extends Creator {
factoryMethod() { return new ConcreteProductA(); }
}
Java 实现
interface Product { String operation(); }
class ProductA implements Product { public String operation() { return "A"; } }
class ProductB implements Product { public String operation() { return "B"; } }
abstract class Creator {
abstract Product factoryMethod();
public String someOperation() {
Product product = factoryMethod();
return "Creator worked with " + product.operation();
}
}
class CreatorA extends Creator {
public Product factoryMethod() { return new ProductA(); }
}
3. 抽象工厂模式(Abstract Factory)
意图:提供一个创建一系列相关或相互依赖对象的接口,无需指定具体类。
典型场景:跨平台 UI 套件(Windows 按钮 / Mac 按钮)、主题皮肤切换。
TypeScript 实现
interface Button { paint(): void; }
interface Checkbox { paint(): void; }
class WinButton implements Button { paint() { /* Windows style */ } }
class MacButton implements Button { paint() { /* Mac style */ } }
interface GUIFactory {
createButton(): Button;
createCheckbox(): Checkbox;
}
class WinFactory implements GUIFactory {
createButton() { return new WinButton(); }
// ...
}
Java 实现
interface Button { void paint(); }
interface Checkbox { void paint(); }
class WinButton implements Button { public void paint() { /* ... */ } }
class MacButton implements Button { public void paint() { /* ... */ } }
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
class WinFactory implements GUIFactory {
public Button createButton() { return new WinButton(); }
// ...
}
4. 建造者模式(Builder)
意图:将一个复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示。
典型场景:创建复杂的 SQL 查询、HTTP 请求构造、文档生成。
TypeScript 实现
class Pizza {
dough: string; sauce: string; topping: string;
constructor(builder: PizzaBuilder) {
this.dough = builder.dough;
this.sauce = builder.sauce;
this.topping = builder.topping;
}
}
class PizzaBuilder {
dough: string = 'thin';
sauce: string = 'tomato';
topping: string = 'cheese';
setDough(dough: string) { this.dough = dough; return this; }
setSauce(sauce: string) { this.sauce = sauce; return this; }
build() { return new Pizza(this); }
}
// 使用:new PizzaBuilder().setDough('thick').build();
Java 实现
public class Pizza {
private String dough;
private String sauce;
private String topping;
private Pizza(Builder builder) {
this.dough = builder.dough;
this.sauce = builder.sauce;
this.topping = builder.topping;
}
public static class Builder {
private String dough = "thin";
private String sauce = "tomato";
private String topping = "cheese";
public Builder setDough(String dough) { this.dough = dough; return this; }
public Builder setSauce(String sauce) { this.sauce = sauce; return this; }
public Pizza build() { return new Pizza(this); }
}
}
5. 原型模式(Prototype)
意图:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
典型场景:需要频繁创建相似复杂对象、避免使用 new 的代价。
TypeScript 实现
interface Prototype { clone(): Prototype; }
class Sheep implements Prototype {
name: string;
clone(): Sheep { return Object.assign(Object.create(this), this); }
}
Java 实现(实现 Cloneable)
public class Sheep implements Cloneable {
private String name;
public Sheep clone() throws CloneNotSupportedException {
return (Sheep) super.clone();
}
}
二、结构型模式(7种)
1. 适配器模式(Adapter)
意图:将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以一起工作。
典型场景:旧系统兼容、第三方库集成。
TypeScript 实现
class OldSystem { specificRequest(): string { return 'old'; } }
interface Target { request(): string; }
class Adapter implements Target {
private adaptee: OldSystem;
constructor(adaptee: OldSystem) { this.adaptee = adaptee; }
request(): string { return `adapted: ${this.adaptee.specificRequest()}`; }
}
Java 实现
class OldSystem { String specificRequest() { return "old"; } }
interface Target { String request(); }
class Adapter implements Target {
private OldSystem adaptee;
public Adapter(OldSystem adaptee) { this.adaptee = adaptee; }
public String request() { return "adapted: " + adaptee.specificRequest(); }
}
2. 装饰器模式(Decorator)
意图:动态地给对象添加额外职责,比继承更灵活。
典型场景:流处理、中间件、UI 组件的动态增强。
TypeScript 实现
interface Coffee { cost(): number; }
class SimpleCoffee implements Coffee { cost() { return 5; } }
abstract class CoffeeDecorator implements Coffee {
protected coffee: Coffee;
constructor(coffee: Coffee) { this.coffee = coffee; }
abstract cost(): number;
}
class MilkDecorator extends CoffeeDecorator {
cost() { return this.coffee.cost() + 2; }
}
Java 实现
interface Coffee { int cost(); }
class SimpleCoffee implements Coffee { public int cost() { return 5; } }
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
CoffeeDecorator(Coffee coffee) { this.coffee = coffee; }
public abstract int cost();
}
class MilkDecorator extends CoffeeDecorator {
MilkDecorator(Coffee coffee) { super(coffee); }
public int cost() { return super.coffee.cost() + 2; }
}
3. 代理模式(Proxy)
意图:为另一个对象提供一个替身或占位符,以控制对这个对象的访问。
典型场景:懒加载、访问控制、远程代理。
TypeScript 实现(虚拟代理)
interface Image { display(): void; }
class RealImage implements Image {
display() { console.log('displaying real image'); }
}
class ProxyImage implements Image {
private realImage: RealImage | null = null;
display() {
if (!this.realImage) this.realImage = new RealImage();
this.realImage.display();
}
}
Java 实现
interface Image { void display(); }
class RealImage implements Image {
public void display() { System.out.println("displaying"); }
}
class ProxyImage implements Image {
private RealImage realImage;
public void display() {
if (realImage == null) realImage = new RealImage();
realImage.display();
}
}
其他结构型模式速览
- 桥接模式:分离抽象与实现,使两者可独立变化(如画笔与颜色)
- 组合模式:将对象组合成树形结构以表示“部分-整体”层次
- 外观模式:为复杂子系统提供一个统一的高级接口
- 享元模式:运用共享技术有效支持大量细粒度对象(如字符对象池)
三、行为型模式(11种)
1. 观察者模式(Observer)
意图:定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖者自动收到通知。
典型场景:事件监听、发布-订阅系统、MVC 视图更新。
TypeScript 实现
interface Observer { update(data: string): void; }
class Subject {
private observers: Observer[] = [];
attach(observer: Observer) { this.observers.push(observer); }
notify(data: string) { this.observers.forEach(o => o.update(data)); }
}
class ConcreteObserver implements Observer {
update(data: string) { console.log(`Received: ${data}`); }
}
Java 实现
interface Observer { void update(String data); }
class Subject {
private List<Observer> observers = new ArrayList<>();
void attach(Observer o) { observers.add(o); }
void notify(String data) { observers.forEach(o -> o.update(data)); }
}
class ConcreteObserver implements Observer {
public void update(String data) { System.out.println("Received: " + data); }
}
2. 策略模式(Strategy)
意图:定义一系列算法,把它们封装起来,并使它们可以相互替换。
典型场景:支付方式选择、压缩算法、表单验证规则。
TypeScript 实现
interface SortStrategy { sort(data: number[]): number[]; }
class BubbleSort implements SortStrategy { sort(data: number[]) { /* ... */ } }
class QuickSort implements SortStrategy { sort(data: number[]) { /* ... */ } }
class Sorter {
constructor(private strategy: SortStrategy) {}
setStrategy(strategy: SortStrategy) { this.strategy = strategy; }
sort(data: number[]) { return this.strategy.sort(data); }
}
Java 实现
interface SortStrategy { int[] sort(int[] data); }
class BubbleSort implements SortStrategy { public int[] sort(int[] data) { /* ... */ } }
class QuickSort implements SortStrategy { public int[] sort(int[] data) { /* ... */ } }
class Sorter {
private SortStrategy strategy;
public Sorter(SortStrategy s) { this.strategy = s; }
public void setStrategy(SortStrategy s) { this.strategy = s; }
public int[] sort(int[] data) { return strategy.sort(data); }
}
3. 模板方法模式(Template Method)
意图:在一个方法中定义算法的骨架,而将一些步骤延迟到子类中实现。
典型场景:框架生命周期、数据处理流水线。
TypeScript 实现
abstract class DataProcessor {
process(): void {
this.loadData();
this.parseData();
this.saveData();
}
abstract loadData(): void;
abstract parseData(): void;
saveData(): void { console.log('default save'); }
}
class CSVProcessor extends DataProcessor {
loadData() { /* load CSV */ }
parseData() { /* parse */ }
}
Java 实现
abstract class DataProcessor {
public final void process() {
loadData();
parseData();
saveData();
}
abstract void loadData();
abstract void parseData();
void saveData() { System.out.println("default save"); }
}
class CSVProcessor extends DataProcessor {
void loadData() { /* load CSV */ }
void parseData() { /* parse */ }
}
其他行为型模式速览
- 责任链模式:多个处理器依次处理请求,直到有一个能处理它
- 命令模式:将请求封装为对象,支持撤销、排队等
- 解释器模式:定义语言的文法并解释执行
- 迭代器模式:提供一种方法顺序访问聚合对象中各个元素,而不暴露内部表示
- 中介者模式:用一个中介对象封装一系列对象的交互
- 备忘录模式:在不破坏封装的前提下捕获对象内部状态,以便后续恢复
- 状态模式:允许对象在内部状态改变时改变其行为
- 访问者模式:在不改变元素类的前提下定义作用于这些元素的新操作
总结与学习建议
设计模式不是银弹,但它们提供了经过验证的词汇表和可复用的解决方案。在实际项目中:
- 优先理解模式解决的问题上下文,而非死记结构。
- 从Strategy、Observer、Decorator、Factory Method等高频模式入手。
- 在重构时引入模式,而非过度设计。
- 记住“高内聚、低耦合”是最终目的,模式只是手段。
现在,打开你的 IDE,挑一个模式写个小 Demo 吧。只有亲手编码,才能真正内化这些经典智慧。