1. 设计模式基础认知
第一次接触设计模式是在重构一个电商促销系统时。当时代码里充斥着大量if-else逻辑,新增促销类型需要修改核心计算类,每次上线都战战兢兢。直到团队引入策略模式,才真正体会到"对修改关闭,对扩展开放"的精妙。设计模式不是银弹,但确实是程序员从"能干活"到"会设计"的关键跃迁。
设计模式本质是前辈总结的23种典型场景解决方案,就像建筑领域的标准结构图纸。Gof在《设计模式》中将其分为创建型(解决对象创建问题)、结构型(处理类与对象组合)、行为型(定义对象交互方式)三大类。掌握这些模式的价值在于:
- 提升代码复用性,避免重复造轮子
- 增强系统扩展性,降低功能迭代成本
- 改善代码可读性,形成团队共同语言
- 规避常见设计缺陷,如循环依赖等
重要提示:切忌为了用模式而用模式。我曾见过把简单工厂强行改造成抽象工厂的案例,反而让系统复杂度陡增。模式是手段不是目的,适合的才是最好的。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 创建型模式实战解析
2.1 单例模式(Singleton)
在全局配置管理中,我们绝对不希望出现多个配置实例互相覆盖的情况。单例模式通过私有构造+静态实例确保全局唯一性。现代实现更推荐双重检查锁(DCL)方式:
java复制public class ConfigManager {
private static volatile ConfigManager instance;
private ConfigManager() {}
public static ConfigManager getInstance() {
if (instance == null) {
synchronized (ConfigManager.class) {
if (instance == null) {
instance = new ConfigManager();
}
}
}
return instance;
}
}
典型应用场景:
- 数据库连接池
- 日志处理器
- 应用级缓存
踩坑记录:
- 多线程环境下懒汉式需要volatile防止指令重排序
- 反射攻击可能破坏单例,可在构造器添加防御代码
- 分布式环境需改用分布式锁或外部存储方案
2.2 工厂方法模式(Factory Method)
在开发跨平台UI组件时,按钮创建逻辑因操作系统而异。工厂方法将实例化延迟到子类:
python复制from abc import ABC, abstractmethod
class Button(ABC):
@abstractmethod
def render(self): pass
class WindowsButton(Button):
def render(self): return "Windows风格按钮"
class MacButton(Button):
def render(self): return "Mac风格按钮"
class Dialog(ABC):
@abstractmethod
def create_button(self) -> Button: pass
def render(self):
button = self.create_button()
return button.render()
class WindowsDialog(Dialog):
def create_button(self) -> Button:
return WindowsButton()
class MacDialog(Dialog):
def create_button(self) -> Button:
return MacButton()
模式优势:
- 符合开闭原则,新增平台无需修改现有代码
- 客户端代码与具体产品解耦
- 便于实现依赖注入框架
3. 结构型模式深度应用
3.1 适配器模式(Adapter)
对接第三方支付接口时,对方返回的JSON格式与我们内部DTO结构不匹配。此时适配器就像转接头:
typescript复制// 第三方接口返回结构
interface AliPayResponse {
ali_order_id: string;
total_amount: number;
pay_status: 0 | 1;
}
// 系统内部标准结构
interface PaymentResult {
orderId: string;
amount: number;
success: boolean;
}
class AliPayAdapter implements PaymentResult {
constructor(private aliPayRes: AliPayResponse) {}
get orderId() { return this.aliPayRes.ali_order_id; }
get amount() { return this.aliPayRes.total_amount; }
get success() { return this.aliPayRes.pay_status === 1; }
}
// 使用示例
const aliResponse = await fetchAliPayResult();
const adaptedResult = new AliPayAdapter(aliResponse);
processPayment(adaptedResult);
适用场景对比:
| 场景特征 | 适配器模式 | 装饰器模式 |
|---|---|---|
| 接口转换 | ✓ | × |
| 功能增强 | × | ✓ |
| 保持原接口 | × | ✓ |
| 解决兼容性问题 | ✓ | × |
3.2 组合模式(Composite)
实现企业组织架构权限系统时,组合模式让单个员工和部门可以统一处理:
java复制interface OrganizationComponent {
void add(OrganizationComponent component);
void remove(OrganizationComponent component);
List<OrganizationComponent> getChildren();
void displayPermissions();
}
class Department implements OrganizationComponent {
private List<OrganizationComponent> children = new ArrayList<>();
@Override
public void displayPermissions() {
children.forEach(OrganizationComponent::displayPermissions);
}
// 其他方法实现...
}
class Employee implements OrganizationComponent {
@Override
public void displayPermissions() {
System.out.println("员工权限列表...");
}
// 叶子节点无需实现add/remove
}
实现要点:
- 树枝节点(Department)管理子组件集合
- 叶子节点(Employee)实现原子操作
- 客户端可统一处理简单和复杂元素
4. 行为型模式典型场景
4.1 观察者模式(Observer)
电商订单状态变更通知是经典案例。通过JDK内置实现更简洁:
java复制public class Order {
private String state;
private final List<Observer> observers = new ArrayList<>();
public void addObserver(Observer o) {
observers.add(o);
}
public void setState(String newState) {
this.state = newState;
observers.forEach(o -> o.update(this));
}
}
// 使用示例
Order order = new Order();
order.addObserver(new EmailNotifier());
order.addObserver(new SMSNotifier());
order.setState("PAID"); // 自动触发通知
演进趋势:
- 响应式编程(如RxJava)是观察者模式的升级
- Spring事件机制基于该模式实现
- 注意避免内存泄漏(及时移除观察者)
4.2 策略模式(Strategy)
在物流运费计算系统中,不同运输方式采用不同算法:
go复制type ShippingStrategy interface {
Calculate(weight float64) float64
}
type ExpressShipping struct{}
func (e ExpressShipping) Calculate(w float64) float64 {
return w * 5 + 10
}
type StandardShipping struct{}
func (s StandardShipping) Calculate(w float64) float64 {
return w * 2
}
type ShippingCalculator struct {
strategy ShippingStrategy
}
func (sc *ShippingCalculator) SetStrategy(s ShippingStrategy) {
sc.strategy = s
}
func (sc ShippingCalculator) Quote(weight float64) float64 {
return sc.strategy.Calculate(weight)
}
模式优势:
- 避免多重条件语句
- 算法可独立于客户端变化
- 便于单元测试(可mock策略)
5. 模式选择与组合实践
5.1 模式组合案例:电商购物车
mermaid复制classDiagram
class Cart {
-items: List<CartItem>
+applyPromotion(PromotionStrategy)
+checkout(PaymentStrategy)
}
class PromotionStrategy {
<<interface>>
+apply(Cart)
}
class PaymentStrategy {
<<interface>>
+pay(amount)
}
Cart --> PromotionStrategy
Cart --> PaymentStrategy
设计亮点:
- 策略模式处理促销和支付
- 组合模式管理商品项
- 工厂方法创建不同促销策略
- 观察者通知库存系统
5.2 反模式警示
在微服务架构下,这些模式需要调整:
- 单例模式→改用分布式缓存
- 观察者模式→改用消息队列
- 策略模式→可下沉到服务网格
我曾见过将传统设计模式生搬硬套到云原生系统的失败案例。架构演进要求我们理解模式本质而非形式,比如:
- 单例的本质是控制实例数量
- 观察者的本质是状态变更通知
- 策略的本质是算法替换
6. 现代框架中的模式演进
Spring框架堪称设计模式教科书:
- 依赖注入:组合工厂模式+策略模式
- @EventListener:观察者模式变体
- RestTemplate:模板方法模式
- @Scope("prototype"):原型模式实现
以Spring Cloud Gateway的过滤器链为例,完美演绎了责任链模式:
java复制public interface GatewayFilter {
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
public class GatewayFilterChain {
private final List<GatewayFilter> filters;
public Mono<Void> filter(ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < filters.size()) {
GatewayFilter filter = filters.get(this.index++);
return filter.filter(exchange, this);
}
return Mono.empty();
});
}
}
这种实现方式既保持了过滤器独立性,又实现了灵活组合。
