设计原则之迪米特

文章目录

一、迪米特原则(LoD)的核心定义

迪米特原则也被称为 "最少知识原则"(Least Knowledge Principle),核心思想是:一个对象应该对其他对象保持最少的了解

用更具体的 C++ 场景描述:

  1. 一个类只应该和它的 "直接朋友" 交互(直接朋友包括:成员变量、方法参数、方法返回值、当前对象本身、方法内创建的局部对象);
  2. 不要和 "陌生人" 交互,避免通过一个对象去调用另一个对象的方法(即避免A->B->C->doSomething()这种
    "链式调用")。

二、迪米特原则的 C++ 示例

1. 违反迪米特原则的示例

假设你设计一个订单系统,包含Order(订单)、User(用户)、Address(地址)三个类,违反原则的写法如下:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

// 地址类
class Address {
private:
    string detail; // 详细地址
public:
    Address(string d) : detail(d) {}
    string getDetail() const { return detail; }
};

// 用户类
class User {
private:
    Address addr; // 用户的地址(直接朋友)
public:
    User(string addrDetail) : addr(addrDetail) {}
    Address getAddress() const { return addr; }
};

// 订单类
class Order {
private:
    User user; // 订单所属用户(直接朋友)
public:
    Order(string userName, string addrDetail) : user(addrDetail) {}
    
    // 违反迪米特原则:通过User(直接朋友)去调用Address(陌生人)的方法
    void printUserAddress() {
        // 错误:Order只该和User交互,不该直接操作Address
        cout << "用户地址:" << user.getAddress().getDetail() << endl;
    }
};

int main() {
    Order order("张三", "北京市海淀区XX街XX号");
    order.printUserAddress();
    return 0;
}

这里Order类通过User对象直接调用Address的getDetail()方法,Address是Order的 "陌生人",违反了迪米特原则。

2. 遵循迪米特原则的修正示例

核心思路:让User提供获取地址的接口,Order只和User交互,不直接接触Address:

cpp 复制代码
#include <iostream>
#include <string>
using namespace std;

class Address {
private:
    string detail;
public:
    Address(string d) : detail(d) {}
    string getDetail() const { return detail; }
};

class User {
private:
    Address addr;
public:
    User(string addrDetail) : addr(addrDetail) {}
    
    // 新增:让User对外提供获取地址的接口,封装Address的细节
    string getUserAddress() const {
        return addr.getDetail();
    }
};

class Order {
private:
    User user;
public:
    Order(string userName, string addrDetail) : user(addrDetail) {}
    
    // 遵循迪米特原则:只和直接朋友User交互
    void printUserAddress() {
        cout << "用户地址:" << user.getUserAddress() << endl;
    }
};

int main() {
    Order order("张三", "北京市海淀区XX街XX号");
    order.printUserAddress();
    return 0;
}

三、违反迪米特原则的危害

1. 代码耦合度极高

违反 LoD 的代码会形成 "链式依赖"(如A->B->C->D),任何一个中间类的修改(比如C的方法名、返回值变化),都会导致所有依赖这条链的类(如A、B)需要修改;

例如前面的示例中,如果Address的getDetail()改名为getAddressDetail(),违反 LoD 的Order类必须直接修改,而遵循 LoD 的Order类完全不需要动,只改User即可。
2. 代码可读性和可维护性极差

过多的跨层级调用会让代码逻辑变得混乱,阅读代码时需要层层追溯(比如看Order的printUserAddress,需要先看User,再看Address);

维护时定位问题困难,一个 bug 可能牵扯多个类,排查成本高。
3. 代码复用性降低

高耦合的类无法独立复用:比如想把Order类复用在另一个系统中,必须同时带上User和Address,甚至可能因为Address的差异导致无法复用;

而遵循 LoD 的类只依赖直接朋友,复用性更高。
4. 增加测试难度

单元测试需要模拟依赖对象,违反 LoD 的类依赖多个 "陌生人",需要模拟的对象更多、逻辑更复杂;

例如测试Order的printUserAddress,违反 LoD 的版本需要同时模拟User和Address,而遵循 LoD 的版本只需要模拟User即可。

四、总结

  1. 迪米特原则的核心是 "最少知识":对象只和直接朋友交互,封装陌生人的细节,避免跨层级调用;
  2. 违反迪米特原则的核心危害是高耦合,进而导致代码可维护性、可读性、复用性下降,测试难度增加;
  3. 在 C++ 中遵循迪米特原则的关键是合理封装:让直接朋友对外提供统一接口,隐藏内部依赖的细节。
相关推荐
Xzh042318 分钟前
AI Agent 学习路线(Java 后端方向)
java·人工智能·学习
做cv的小昊1 小时前
计算机图形学:【Games101】学习笔记08——光线追踪(辐射度量学、渲染方程与全局光照、蒙特卡洛积分与路径追踪)
图像处理·笔记·学习·计算机视觉·游戏引擎·图形渲染·概率论
星恒随风1 小时前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
艾利克斯冰1 小时前
Java 设计模式-行为型模式(更新中)
java·开发语言·设计模式
浪客灿心1 小时前
项目篇:模块设计与实现
数据库·c++
牛油果子哥q2 小时前
【C++ STL vector】C++ STL vector 终极精讲:动态数组底层原理、两倍扩容机制、迭代器失效、增删查改、性能剖析与工程避坑指南
开发语言·c++
sensen_kiss3 小时前
CPT304 SoftwareEngineeringII 软件工程 2 Pt.8 软件测试 (Software Testing)(上)
学习·软件工程
力学与人工智能3 小时前
PPT分享 | 洛桑联邦理工学院魏震:深度几何学习在工业设计优化中的应用
学习·优化·工业设计·深度几何学习·洛桑联邦理工学院
为何创造硅基生物3 小时前
独占指针的创建std::make_unique 本身自带堆出现
c++
kyle~4 小时前
ROS 2 与 Isaac Sim 联合仿真(一)体系架构、环境选型与基础通信闭环
c++·机器人·nvidia·仿真·ros2