迪米特法则也称为"最少知识原则",是降低代码耦合度的关键设计原则。它通过限制对象间的交互范围,提高系统的模块化、可维护性和可测试性。
核心定义
一个对象应当对其他对象有最少的了解:只与直接的朋友通信,不与"陌生人"说话。
三大核心规则
-
有限范围规则:对象的方法只能访问
- 对象自身的属性
- 方法参数传入的对象
- 方法内创建的对象
- 对象的直接组件对象
-
禁止链式调用:避免出现长链式访问
a.getB().getC().doSomething() -
封装控制原则:不让外部直接操作内部组件状态
C++ 代码示例
违反 LoD 的典型例子
class Engine {
public:
void start() { /* 启动引擎 */ }
};
class CarDoor {
public:
void open() { /* 开门 */ }
};
// 错误实现:暴露内部组件
class Car {
public:
Engine* getEngine() { return &engine_; } // ❌ 暴露内部组件
CarDoor* getDoor() { return &door_; } // ❌ 暴露内部组件
void operate() {
// ❌ 链式调用:Car→Engine
getEngine()->start();
}
private:
Engine engine_;
CarDoor door_;
};
// 客户端代码违反 LoD
void clientCode() {
Car myCar;
// 🚫 直接访问内部组件(危险!)
myCar.getDoor()->open();
// 🚫 深层链式调用
myCar.getEngine()->start();
}
遵循 LoD 的重构实现
class Car {
public:
// ✅ 封装内部操作
void unlock() { door_.open(); }
void start() { engine_.start(); }
// ✅ 禁止外部访问内部组件
// 不再提供 getEngine()/getDoor() 方法
private:
Engine engine_;
CarDoor door_;
};
// 客户端安全使用
void clientCode() {
Car myCar;
myCar.unlock(); // ✅ 只与直接朋友通信
myCar.start(); // ✅ 通过封装方法控制
}
深度应用场景
1. 多层嵌套对象访问
// 🚫 违反 LoD:三层链式访问
class A {
public:
B* getB() { return b_; } // ❌ 暴露内部组件
private:
B* b_;
};
class B {
public:
C* getC() { return c_; } // ❌ 暴露内部组件
private:
C* c_;
};
// 客户端问题代码
a.getB()->getC()->doAction();
// ✅ 重构方案:中间层封装
class A {
public:
void performAction() { // 封装访问链
b_->getC()->doAction();
}
};
2. STL 容器封装
class Library {
public:
// 🚫 违反 LoD:返回内部容器引用
std::vector<Book>& getBooks() { return books_; }
// ✅ 遵循 LoD:封装访问方法
void addBook(const Book& book) {
books_.push_back(book);
}
Book findBook(const std::string& isbn) const {
auto it = std::find_if(books_.begin(), books_.end(),
[&](const Book& b) { return b.isbn == isbn; });
return (it != books_.end()) ? *it : Book{};
}
private:
std::vector<Book> books_;
};
设计模式中的应用
1. 外观模式(Facade)
// 复杂子系统
class CPU { public: void execute() {} };
class Memory { public: void load() {} };
class HardDrive { public: void read() {} };
// ✅ Facade 封装
class ComputerFacade {
public:
void start() {
memory_.load(0, hd_.read(BOOT_SECTOR));
cpu_.execute(0, 100);
}
private:
CPU cpu_;
Memory memory_;
HardDrive hd_;
};
// 客户端只需与 Facade 交互
ComputerFacade computer;
computer.start(); // 隐藏了内部组件交互
2. 中介者模式(Mediator)
class UIControl {
protected:
Mediator* mediator_;
public:
UIControl(Mediator* m) : mediator_(m) {}
};
class Button : public UIControl {
using UIControl::UIControl;
void click() {
mediator_->notify(this, "click"); // 仅与中介者通信
}
};
class Mediator {
void notify(UIControl* sender, const std::string& event) {
// 处理控件间交互逻辑
}
};
C++ 特殊优化策略
1. 方法返回值优化
class ReportGenerator {
public:
// ✅ 返回值而非引用/指针
Report generateReport() {
Report report;
// ...填充报告数据
return report; // RVO/NRVO 避免拷贝
}
};
2. 移动语义支持
class DataProcessor {
public:
// ✅ 高效返回大型对象
BigData process() {
BigData data;
// ...处理数据
return data; // 启用移动语义
}
};
3. 返回智能指针的封装
class ResourceManager {
public:
// ✅ 封装资源访问
void useResource() {
auto resource = getResource();
resource->operate();
}
private:
std::unique_ptr<Resource> getResource() {
return std::make_unique<ResourceImpl>();
}
};
性能与设计平衡策略
| 场景 | 推荐方案 | 性能影响 |
|---|---|---|
| 高频调用的简单数据访问 | 适度放宽 LoD (直接访问) | ⚡ 最优性能 |
| 跨模块边界交互 | 严格遵守 LoD (完全封装) | 🔒 最佳封装性 |
| 大型数据集合访问 | 提供迭代器/范围访问 | ⚖️ 平衡封装和效率 |
| 组件层级交互 | 使用中介者/外观模式 | 🛡️ 最佳解耦效果 |
LoD 实施检查清单
-
是否避免了超过一层的方法调用链?
// ❌ 禁止写法 objA.getB().getC().doAction(); // ✅ 允许写法 objA.executeAction(); -
是否禁止返回内部组件的引用/指针?
// ❌ 非法暴露 const std::vector<Item>& getItems(); // ✅ 安全封装 const Item& getItem(size_t index); void forEachItem(std::function<void(const Item&)> callback); -
是否将相关操作封装在当前对象中?
// ❌ 分散在客户端 void clientCode() { if (car.getDoor().isLocked()) { car.getDoor().unlock(); } } // ✅ 对象自我管理 class Car { void enter() { if (door_.isLocked()) { door_.unlock(); } } }; -
是否避免了在参数中传递复杂结构?
// ❌ 暴露内部结构 void printDepartmentInfo(Employee& e) { cout << e.getDepartment().getName(); } // ✅ 对象提供完整接口 void printDepartmentInfo(Employee& e) { cout << e.getDepartmentName(); }
LoD 与其它原则的协同
| 原则 | 协同效果 |
|---|---|
| SRP | 共同降低类复杂度,提高内聚性 |
| OCP | 封装变化点,减少修改波及范围 |
| ISP | 精细接口自然满足 LoD 的"最少知识"要求 |
| DIP | 依赖抽象避免知晓具体实现细节 |
迪米特法则在C++系统设计中可降低50%+的模块间耦合(根据工业界数据统计)。尤其在大型系统、安全关键系统(如自动驾驶、航空航天)中,遵循LoD可显著提高代码可靠性和可维护性。
1110

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



