SOLID 原则(面向对象设计的五条基本准则)
SOLID 是面向对象设计的五条原则组合,有助于提高代码可维护性、可扩展性与可测试性。每条原则都简短明确 —— 下面逐条说明并给出简洁的 C++ 风格示例与常见陷阱。
S — Single Responsibility Principle(单一职责原则)
一句话:一个类应该只有一个引起它变化的原因。
要点:把不同关注点分离到不同类里,避免“上帝类”。
// 坏:Logger 和 数据访问混在一起
class UserRepository {
public:
User getUser(int id);
void log(const std::string& msg); // 不属于仓库职责
};
// 好:职责分离
class Logger { public: void log(const std::string&); };
class UserRepository {
Logger& logger;
public:
UserRepository(Logger& l): logger(l) {}
User getUser(int id) { logger.log("getUser"); /*...*/ }
};
常见陷阱:把 UI、业务、持久化、日志等职责堆到一个类里。
O — Open/Closed Principle(开闭原则)
一句话:对扩展开放,对修改关闭 — 新需求通过扩展(继承/组合/策略)实现,而不是改现有代码。
要点:使用抽象接口与多态,避免修改现有类来添加新行为。
struct Shape { virtual double area() const = 0; };
struct Circle : Shape { double r; double area() const override { return 3.14*r*r; } };
struct Rectangle : Shape { double w,h; double area() const override { return w*h; } };
double totalArea(const std::vector<Shape*>& shapes){
double sum=0; for(auto s: shapes) sum += s->area();
return sum;
}
// 新增 Triangle 不改 totalArea,符合开闭
常见陷阱:直接在已有类中增加 if/else 分支来处理新类型。
L — Liskov Substitution Principle(里氏替换原则)
一句话:子类应能替换父类且不破坏程序正确性。
要点:子类不能违反父类的契约(行为/前置后置条件、异常语义等)。
class Bird { public: virtual void fly() {} };
class Ostrich : public Bird {
// 如果父类假定所有 Bird 都能 fly,Ostrich 就破坏了这个契约
void fly() override { throw std::runtime_error("can't fly"); }
};
应对方法:重构抽象(把可飞行为抽成 IFlyable 接口),或重新设计继承层次。
I — Interface Segregation Principle(接口隔离原则)
一句话:客户端不应被迫依赖它不使用的方法 —— 用多个小接口替代大接口。
要点:把“胖接口”拆成更小的、角色相关的接口。
struct IPrinter { virtual void print() = 0; virtual void scan() = 0; };
// 若有只打印的设备,被迫实现 scan 就违背了 ISP
struct IPrinter { virtual void print() = 0; };
struct IScanner { virtual void scan() = 0; };
D — Dependency Inversion Principle(依赖倒置原则)
一句话:高层模块不应该依赖低层模块,二者都应该依赖抽象(接口);抽象不应依赖细节,细节应依赖抽象。
要点:通过接口和依赖注入(构造注入/工厂)解耦实现细节。
struct IMessageSender { virtual void send(const std::string&)=0; };
class EmailSender : public IMessageSender { void send(const std::string& m) override {/*...*/} };
class Notification {
IMessageSender& sender;
public:
Notification(IMessageSender& s): sender(s) {}
void notify(const std::string& msg) { sender.send(msg); }
};
// Notification 只依赖 IMessageSender(抽象),不依赖 EmailSender(细节)
实用建议(把原则落地)
-
先写小接口、单一职责的类;当代码变化点集中时考虑抽象与分离。
-
以测试驱动或模块化重构推动开闭与依赖倒置(引入接口再注入实现)。
-
里氏原则常被忽视——重构继承为组合通常更安全。
-
不要机械套用 SOLID —— 它们是指导原则,工程中需权衡(过度抽象会增加复杂度)。
-
在团队里把 SOLID 与代码审查/PR 规则结合,逐步改进遗留代码。
261

被折叠的 条评论
为什么被折叠?



