单一职责原则(Single Responsibility Principle, SRP)是面向对象设计五大原则(SOLID)中的第一个

单一职责原则(Single Responsibility Principle, SRP)是面向对象设计五大原则(SOLID)中的第一个,其核心思想是:一个类(或模块、函数)应该且仅应有一个引起它变化的原因,即只承担一种职责。

  • ✅ 正确实践:如 UserRepository 仅负责数据库的用户数据存取,UserService 仅负责业务逻辑编排;
  • ❌ 违反表现:一个 UserManager 类既处理用户注册验证、又写日志、又发邮件、又更新缓存——任一需求变更(如更换邮件服务)都可能迫使修改该类,导致高耦合、低内聚、测试困难、易出错;
  • 🛠 应对策略:通过职责识别→提取共性→拆分为更小单元(如 EmailNotifierCacheUpdater),再用组合(而非继承)或设计模式(如代理模式封装调用、装饰器模式动态增强行为)解耦协作。
# 示例:违反SRP的类(重构前)
class UserManager:
    def register(self, user):
        # 验证 + 保存 + 发邮件 + 记日志 → 四种职责混杂
        if not user.is_valid(): return False
        db.save(user)
        send_email(user.email, "Welcome!")
        log.info(f"User {user.id} registered")
        return True

# 重构后:各司其职
class UserRepository:
    def save(self, user): ...

class EmailNotifier:
    def notify(self, user): ...

class UserRegistrationService:
    def __init__(self, repo: UserRepository, notifier: EmailNotifier, logger: Logger):
        self.repo = repo
        self.notifier = notifier
        self.logger = logger

    def register(self, user):
        if not user.is_valid(): return False
        self.repo.save(user)
        self.notifier.notify(user)
        self.logger.info(...)
        return True

准确识别一个类是否违反单一职责原则(SRP),关键在于审视其变更原因的数量:若该类因多种不同业务目标、技术需求或利益相关方(如产品经理、运维、安全团队)的要求而需要修改,即存在多个“变化原因”,则已违反SRP。

以下是常见的 “职责信号”(Smells of SRP Violation),可作为代码审查和重构的实用检查清单:

1. 方法功能跨度大

  • 同一方法中混合:数据校验 + 持久化 + 网络调用 + 日志记录 + 通知发送;
  • 类中同时出现 saveToDB()sendEmail()generateReport()validateInput() 等语义完全无关的方法。

2. 引入过多依赖(高耦合)

  • 类的构造函数/注入列表包含跨领域对象:如同时依赖 DatabaseConnectionSMTPClientRedisCacheMetricsReporterAuditLogger
    → 暗示它在协调多个系统关注点,而非专注自身核心逻辑。

3. 注释/命名暴露多意图

  • 类名含“Manager”“Handler”“Processor”“Utils”等模糊词(如 OrderManagerFileProcessor)且无明确边界;
  • 方法注释频繁出现“同时…”“另外…”“还要…”(例:“验证用户,同时更新积分,还要发站内信并记录审计日志”)。

4. 测试用例类型混杂

  • 单元测试文件中需 mock 数据库、邮件服务、第三方API、缓存等多个外部系统;
  • 一个测试方法既验证业务规则,又断言日志内容、邮件模板、HTTP状态码——说明测试在验证多个契约。

5. 修改引发意外副作用

  • 仅因“增加短信通知”就需修改该类,结果导致原有邮件发送逻辑出错或缓存失效;
  • 发布后出现非预期故障(如改日志级别导致事务回滚失败),表明职责纠缠。

🔍 辅助判断技巧

  • “如果……会怎样?”提问法
    ▪ 如果产品要求“注册成功后不再发邮件”,是否要改这个类?
    ▪ 如果运维要求“日志格式统一为JSON”,是否要改这个类?
    ▪ 如果安全团队要求“密码字段脱敏打印”,是否要改这个类?
    → 若任一答案为“是”,即存在 ≥2 个变化原因,SRP 已被破坏。
# 反例信号集中体现
class PaymentService {  // ❌ 名称宽泛,无领域聚焦
    private Database db;
    private EmailSender email;
    private SmsGateway sms;
    private Cache cache;
    private AuditLogger audit;

    public void process(Payment p) {
        if (!p.isValid()) throw ...;              // 验证
        db.insert(p);                            // 存储
        cache.evict("user:" + p.userId);         // 缓存
        email.send("paid", p.user);              // 通知
        sms.send(p.user.phone, "Paid!");         // 另一通知
        audit.log("Payment processed", p.id);    // 审计
    }
}
// ✅ 重构方向:拆为 PaymentValidator、PaymentRepository、NotificationService、AuditService 等

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值