# 开闭原则

> 软件应该对扩展开放，对修改关闭。通过抽象和多态，支持通过添加新代码而非修改现有代码来扩展功能。

- Skill: `microwind/skill-91` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add microwind/skill-91`
- Raw SKILL.md: https://api.skillmd.com/api/skills/microwind/skill-91/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: microwind (https://skillmd.com/u/microwind)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/microwind/skill-91

---


# 开闭原则 (Open-Closed Principle, OCP)

## 概述

开闭原则是SOLID中最重要的一个，它定义了优秀设计的本质：**对扩展开放，对修改关闭**。

**核心思想**：
- 通过抽象实现扩展开放
- 现有代码永不改动，通过新增代码扩展
- 利用继承、接口、组合实现扩展
- 代码变更风险最小化

**关键指标**：
- 新增功能 = 新增类/配置，不修改现有类
- 修改现有类比例 < 5%
- 所有新功能独立实现在新类中

## 何时使用

**始终使用**：
- 业务需求频繁变化
- 系统需要支持多种变体（如支付方式、日志类型）
- 团队协作开发，多人改同一模块
- 代码已上线，修改风险大
- 需要灰度发布或A/B测试

**触发短语**：
- "需要添加新的支付方式，但不想修改现有代码"
- "要支持新的数据库，害怕影响现有功能"
- "多个团队同时开发，容易冲突"
- "已发布的系统，改动必须向后兼容"

## 实现方式

### 1. 通过抽象实现扩展

```java
// ❌ 对修改关闭失败
public class PaymentProcessor {
    public void process(String paymentType, double amount) {
        if ("ALIPAY".equals(paymentType)) {
            // 支付宝逻辑
        } else if ("WECHAT".equals(paymentType)) {
            // 微信逻辑
        } else if ("CARD".equals(paymentType)) {
            // 信用卡逻辑
        }
        // 新增支付方式需要修改这个类
    }
}

// ✅ 对扩展开放，对修改关闭
public interface PaymentGateway {
    void initialize();
    void pay(double amount);
    void refund(double transactionId);
}

public class AlipayGateway implements PaymentGateway { /* ... */ }
public class WechatGateway implements PaymentGateway { /* ... */ }
public class CardGateway implements PaymentGateway { /* ... */ }

public class PaymentProcessor {
    private PaymentGateway gateway;

    public void process(PaymentGateway gateway, double amount) {
        gateway.initialize();
        gateway.pay(amount);
        // 新增支付方式只需创建新的 PaymentGateway 实现
    }
}
```

### 2. 通过配置实现扩展

```java
// 通过配置文件而非代码修改来扩展
public class PaymentFactory {
    private static final Map<String, Class<? extends PaymentGateway>> REGISTRY =
        new ConcurrentHashMap<>();

    public static void registerGateway(String type, Class<? extends PaymentGateway> clazz) {
        REGISTRY.put(type, clazz);
    }

    public static PaymentGateway create(String type) {
        Class<? extends PaymentGateway> clazz = REGISTRY.get(type);
        if (clazz == null) {
            throw new IllegalArgumentException("Unknown payment type: " + type);
        }
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

// 配置驱动（无需修改代码）
public class PaymentConfiguration {
    public void configureGateways() {
        PaymentFactory.registerGateway("ALIPAY", AlipayGateway.class);
        PaymentFactory.registerGateway("WECHAT", WechatGateway.class);
        PaymentFactory.registerGateway("CARD", CardGateway.class);
        // 新增支付方式：PaymentFactory.registerGateway("STRIPE", StripeGateway.class);
    }
}
```

### 3. 通过继承实现扩展

```java
// 基类定义通用逻辑
public abstract class Logger {
    public final void log(String message) {
        String formatted = format(message);
        write(formatted);
    }

    protected String format(String message) {
        return "[" + getCurrentTime() + "] " + message;
    }

    protected abstract void write(String message);

    private String getCurrentTime() {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    }
}

// 扩展：仅需创建新的Logger子类
public class FileLogger extends Logger {
    private PrintWriter writer;

    @Override
    protected void write(String message) {
        writer.println(message);
    }
}

public class DatabaseLogger extends Logger {
    @Override
    protected void write(String message) {
        // 保存到数据库
    }
}

public class RemoteLogger extends Logger {
    @Override
    protected void write(String message) {
        // 发送到远程服务器
    }
}

// 新增Logger无需修改现有代码
```

## 违反OCP的现象

```java
// ❌ 频繁修改现有类
public class ReportGenerator {
    public String generate(String type) {
        if ("PDF".equals(type)) {
            // PDF 生成逻辑
        } else if ("EXCEL".equals(type)) {
            // Excel 生成逻辑 - 第1次修改
        } else if ("HTML".equals(type)) {
            // HTML 生成逻辑 - 第2次修改
        } else if ("CSV".equals(type)) {
            // CSV 生成逻辑 - 第3次修改
        }
        // 每增加一种格式都要修改这个类
    }
}

// ✅ 遵循OCP
public interface ReportFormatter {
    String format(Report report);
}

public class PdfFormatter implements ReportFormatter { }
public class ExcelFormatter implements ReportFormatter { }
public class HtmlFormatter implements ReportFormatter { }
public class CsvFormatter implements ReportFormatter { }

public class ReportGenerator {
    public String generate(Report report, ReportFormatter formatter) {
        return formatter.format(report);
        // 新增格式无需修改这个类
    }
}
```

## 优缺点分析

### ✅ 优点

1. **降低变更风险** - 现有代码不改，新增代码自动应用
2. **增强代码稳定性** - 已测试的代码保持不变
3. **支持多人协作** - 各团队开发不同的扩展，无冲突
4. **促进代码复用** - 基础类通过继承/组合被复用
5. **便于测试** - 新功能独立测试，无需回归测试
6. **易于维护** - 清晰的职责分离，便于定位问题

### ❌ 缺点

1. **设计复杂** - 需要提前识别变化点
2. **代码增加** - 抽象层增加代码量
3. **过度设计风险** - 猜测变化导致不必要的抽象
4. **学习曲线** - 继承、接口、组合等需要理解
5. **性能开销** - 多一层抽象调用可能有微小性能影响

## 最佳实践

### 1️⃣ 识别变化点

```
在设计时问自己：
□ 这个功能将来可能如何改变？
□ 有多少种实现方式？
□ 是否会有新的实现？

在这些地方设置抽象：
```

### 2️⃣ 使用 Template Method 模式

```java
// 基类定义框架，子类实现细节
public abstract class DataProcessor {
    public final void process(String data) {
        // 固定流程（对修改关闭）
        String validated = validate(data);
        String transformed = transform(validated);
        save(transformed);
    }

    protected abstract String validate(String data);
    protected abstract String transform(String data);
    protected abstract void save(String data);
}

// 新增处理器，仅需实现细节
public class CsvDataProcessor extends DataProcessor {
    @Override
    protected String validate(String data) { }
    @Override
    protected String transform(String data) { }
    @Override
    protected void save(String data) { }
}
```

### 3️⃣ 使用 Strategy 模式

```java
public interface SortingStrategy {
    <T extends Comparable<T>> List<T> sort(List<T> list);
}

public class QuickSort implements SortingStrategy { /* ... */ }
public class MergeSort implements SortingStrategy { /* ... */ }
public class BubbleSort implements SortingStrategy { /* ... */ }

public class Sorter {
    private SortingStrategy strategy;

    public void setStrategy(SortingStrategy strategy) {
        this.strategy = strategy;
    }

    public <T extends Comparable<T>> List<T> sort(List<T> list) {
        return strategy.sort(list);
        // 新增排序算法无需修改 Sorter
    }
}
```

### 4️⃣ 通过 Decorator 模式扩展功能

```java
public interface Component {
    void operation();
}

public class ConcreteComponent implements Component {
    @Override
    public void operation() { System.out.println("Basic operation"); }
}

// 不修改 ConcreteComponent，通过 Decorator 添加功能
public abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

public class LoggingDecorator extends Decorator {
    public LoggingDecorator(Component component) { super(component); }

    @Override
    public void operation() {
        System.out.println("Before logging");
        super.operation();
        System.out.println("After logging");
    }
}

// 使用
Component component = new ConcreteComponent();
component = new LoggingDecorator(component);
component.operation();  // 自动加上日志
```

## 代码示例 - 完整实现

### Python

```python
from abc import ABC, abstractmethod
from typing import List

# ✅ 遵循OCP的设计

class PaymentGateway(ABC):
    """支付网关接口"""
    @abstractmethod
    def pay(self, amount: float) -> str:
        pass

class AlipayGateway(PaymentGateway):
    def pay(self, amount: float) -> str:
        print(f"Processing Alipay payment: {amount}")
        return "alipay_transaction_123"

class WechatGateway(PaymentGateway):
    def pay(self, amount: float) -> str:
        print(f"Processing WeChat payment: {amount}")
        return "wechat_transaction_456"

class StripeGateway(PaymentGateway):
    def pay(self, amount: float) -> str:
        print(f"Processing Stripe payment: {amount}")
        return "stripe_transaction_789"

class PaymentProcessor:
    """支付处理器 - 对扩展开放"""
    def process(self, gateway: PaymentGateway, amount: float):
        transaction_id = gateway.pay(amount)
        print(f"Payment processed: {transaction_id}")
        return transaction_id

# 使用示例
if __name__ == "__main__":
    processor = PaymentProcessor()

    # 使用支付宝
    processor.process(AlipayGateway(), 100)

    # 使用微信（无需修改PaymentProcessor）
    processor.process(WechatGateway(), 100)

    # 使用Stripe（仅添加新类，无需修改现有代码）
    processor.process(StripeGateway(), 100)
```

### TypeScript

```typescript
// ✅ 遵循OCP的TypeScript设计

interface DataSource {
    read(): string;
    write(data: string): void;
}

class FileDataSource implements DataSource {
    constructor(private path: string) {}

    read(): string {
        console.log(`Reading from file: ${this.path}`);
        return "file data";
    }

    write(data: string): void {
        console.log(`Writing to file: ${this.path}`);
    }
}

class DatabaseDataSource implements DataSource {
    constructor(private connectionString: string) {}

    read(): string {
        console.log(`Reading from database: ${this.connectionString}`);
        return "database data";
    }

    write(data: string): void {
        console.log(`Writing to database: ${this.connectionString}`);
    }
}

class CloudDataSource implements DataSource {
    constructor(private bucket: string) {}

    read(): string {
        console.log(`Reading from cloud bucket: ${this.bucket}`);
        return "cloud data";
    }

    write(data: string): void {
        console.log(`Writing to cloud bucket: ${this.bucket}`);
    }
}

class DataManager {
    constructor(private source: DataSource) {}

    load(): string {
        return this.source.read();
    }

    save(data: string): void {
        this.source.write(data);
    }
}

// 使用示例
const fileSource = new FileDataSource("/path/to/file");
const manager1 = new DataManager(fileSource);
console.log(manager1.load());

// 无需修改DataManager，仅更换DataSource实现
const dbSource = new DatabaseDataSource("connection_string");
const manager2 = new DataManager(dbSource);
console.log(manager2.load());
```

### Java

```java
// ✅ 完整的OCP实现

public interface ReportGenerator {
    String generate(String data);
}

public class PdfReportGenerator implements ReportGenerator {
    @Override
    public String generate(String data) {
        System.out.println("Generating PDF report");
        return "PDF: " + data;
    }
}

public class ExcelReportGenerator implements ReportGenerator {
    @Override
    public String generate(String data) {
        System.out.println("Generating Excel report");
        return "Excel: " + data;
    }
}

public class HtmlReportGenerator implements ReportGenerator {
    @Override
    public String generate(String data) {
        System.out.println("Generating HTML report");
        return "HTML: " + data;
    }
}

public class ReportService {
    public String createReport(String data, ReportGenerator generator) {
        return generator.generate(data);
        // 新增report类型无需修改这个类
    }
}

// 单元测试
@Test
public void testReportGeneration() {
    ReportService service = new ReportService();

    String pdfReport = service.createReport("Sales Data", new PdfReportGenerator());
    assertEquals("PDF: Sales Data", pdfReport);

    String excelReport = service.createReport("Sales Data", new ExcelReportGenerator());
    assertEquals("Excel: Sales Data", excelReport);
}
```

## 与其他原则的关系

OCP与SRP紧密相关：
- **SRP** 让每个类职责单一
- **OCP** 让新增功能不修改现有类

合使用时最强大。

## 何时违反OCP是可以接受的

- 变化点不明确时，不强制抽象
- 实现完全相同的概念，硬性抽象无益
- 性能关键路径，但需有注释说明
- 简单的实验项目或原型

---

## 总结

**OCP核心**：
- 通过抽象和多态支持扩展
- 现有代码永不改动
- 新功能通过新类实现

**实现工具**：
- 接口/抽象类
- 继承
- 组合
- 配置驱动
- Template Method、Strategy、Decorator 等模式

**效果**：
- 代码更稳定
- 降低变更风险
- 易于扩展
- 支持团队协作

遵循OCP的代码在长期维护中价值巨大。

