当前位置: 首页 > article >正文

迪米特原则的理解和实践

        迪米特原则(Law of Demeter,简称LoD),也被称为最少知识原则(Least Knowledge Principle,LKP),是面向对象设计中的一个重要原则。其核心思想是:一个对象应该对其他对象有最少的了解,即一个对象应该尽可能少地了解其直接对象之外的任何对象。本文将详细探讨迪米特原则的理论理解及其在Java实践中的应用。

一、迪米特原则的理论理解

        迪米特原则的核心在于降低类之间的耦合度,提高模块的相对独立性。通过封装和信息隐藏,对象之间的通信应该通过抽象层进行,以减少对象之间的直接依赖。这种设计方式能够提高系统的可维护性和可扩展性,降低代码的依赖性,减少系统中的风险因素。

  1. 降低耦合度
    耦合度是指不同模块之间相互依赖的程度。过高的耦合度会导致代码难以维护和扩展。迪米特原则通过限制对象之间的直接通信,促使开发者使用接口或中间层来进行通信,从而有效地降低系统各部分之间的耦合度。

  2. 提高内聚力
    内聚力是指模块内部各元素间的紧密程度。高内聚力的模块功能更加专一,易于理解和修改。迪米特原则通过限制对象间的直接交流,促使开发者将功能相似的代码组织在一起,提高了模块的内聚力。

  3. 便于测试和重用
    通过遵循迪米特原则,每个类的功能更加单一和明确,这有助于对单个功能进行独立的测试,从而提高代码的可测试性。同时,减少类之间的直接依赖关系,使得类更加容易重用。

  4. 增强系统的可扩展性
    通过降低类之间的耦合,迪米特原则使得系统的某个部分在不改变其他部分的情况下可以进行修改或扩展,从而增强了系统的可扩展性。

二、迪米特原则的实践

        在Java开发中,迪米特原则可以通过多种方式来实现,包括中介者模式、控制反转(IoC)和依赖注入(DI)、事件驱动编程以及模块化设计等。下面通过具体的代码示例来展示迪米特原则的实践。

示例一:中介者模式

        当一个类需要与多个类进行交互时,可以使用中介者模式来降低类之间的直接依赖。中介者负责协调各个类之间的交互,从而减少类之间的直接通信。

// 中介者接口
interface Mediator {
    void send(String message, String colleagueName);
}

// 具体中介者类
class ConcreteMediator implements Mediator {
    private ColleagueA colleagueA;
    private ColleagueB colleagueB;

    public void setColleagueA(ColleagueA colleagueA) {
        this.colleagueA = colleagueA;
    }

    public void setColleagueB(ColleagueB colleagueB) {
        this.colleagueB = colleagueB;
    }

    @Override
    public void send(String message, String colleagueName) {
        if ("A".equals(colleagueName)) {
            colleagueA.receive(message);
        } else if ("B".equals(colleagueName)) {
            colleagueB.receive(message);
        }
    }
}

// 同事类A
class ColleagueA {
    private Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    public void send(String message) {
        mediator.send(message, "B");
    }

    public void receive(String message) {
        System.out.println("ColleagueA received: " + message);
    }
}

// 同事类B
class ColleagueB {
    private Mediator mediator;

    public void setMediator(Mediator mediator) {
        this.mediator = mediator;
    }

    public void send(String message) {
        mediator.send(message, "A");
    }

    public void receive(String message) {
        System.out.println("ColleagueB received: " + message);
    }
}

// 测试类
public class MediatorPatternDemo {
    public static void main(String[] args) {
        Mediator mediator = new ConcreteMediator();

        ColleagueA colleagueA = new ColleagueA();
        ColleagueB colleagueB = new ColleagueB();

        mediator.setColleagueA(colleagueA);
        mediator.setColleagueB(colleagueB);

        colleagueA.setMediator(mediator);
        colleagueB.setMediator(mediator);

        colleagueA.send("Hello B");
        colleagueB.send("Hello A");
    }
}

        在这个示例中,ColleagueA 和 ColleagueB 通过 Mediator 进行通信,而不是直接调用对方的方法。这降低了类之间的耦合度,提高了系统的可维护性和可扩展性。

示例二:控制反转(IoC)和依赖注入(DI)

        控制反转和依赖注入允许我们将依赖关系外部化,并由容器或框架来管理。这样,类之间的依赖关系就变得更加灵活,降低了直接耦合。

// 接口
interface Service {
    void execute();
}

// 具体服务类
class ConcreteService implements Service {
    @Override
    public void execute() {
        System.out.println("Service executed");
    }
}

// 客户端类
class Client {
    private Service service;

    // 构造器注入
    public Client(Service service) {
        this.service = service;
    }

    public void doSomething() {
        service.execute();
    }
}

// 测试类
public class IoCDemo {
    public static void main(String[] args) {
        Service service = new ConcreteService();
        Client client = new Client(service);
        client.doSomething();
    }
}

        在这个示例中,Client 类通过构造器注入的方式依赖 Service 接口,而不是直接依赖 ConcreteService 类。这使得 Client 类更加灵活,可以轻松地替换 Service 的实现。

示例三:迪米特原则的反面示例与推荐用法

        下面通过一个业务场景来展示迪米特原则的反面示例和推荐用法。

反面示例

// 经理类
public class Manager {
    public void checkGoodsCount(Staff staff) {
        List<Good> goodList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            goodList.add(new Good());
        }
        staff.checkCount(goodList);
    }
}

// 员工类
public class Staff {
    public void checkCount(List<Good> goodList) {
        System.out.println("商品数量为: " + goodList.size());
    }
}

// 商品类
public class Good {
}

// 测试类
public class Main {
    public static void main(String[] args) {
        Manager manager = new Manager();
        Staff staff = new Staff();
        manager.checkGoodsCount(staff);
    }
}

        在这个反面示例中,Manager 类直接创建了 Good 对象的列表,并将其传递给 Staff 类。这违反了迪米特原则,因为 Manager 类不应该了解 Good 类的具体实现。

推荐用法

// 经理类
public class Manager {
    public void checkGoodsCount(Staff staff) {
        staff.checkCount();
    }
}

// 员工类
public class Staff {
    public void checkCount() {
        List<Good> goodList = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            goodList.add(new Good());
        }
        System.out.println("商品数量为: " + goodList.size());
    }
}

// 商品类
public class Good {
}

// 测试类
public class Main {
    public static void main(String[] args) {
        Manager manager = new Manager();
        Staff staff = new Staff();
        manager.checkGoodsCount(staff);
    }
}

        在推荐用法中,Manager 类不再直接创建 Good 对象的列表,而是将创建列表的责任交给了 Staff 类。这样,Manager 类只需要知道 Staff 类的接口,而不需要了解 Good 类的具体实现,从而遵循了迪米特原则。

三、总结

        迪米特原则是面向对象设计中的一个重要原则,它强调一个对象应该对其他对象有最少的了解。通过降低类之间的耦合度,提高模块的相对独立性,迪米特原则有助于我们设计出更加灵活、可维护性更高的软件系统。在Java开发中,我们可以利用中介者模式、控制反转(IoC)和依赖注入(DI)、事件驱动编程以及模块化设计等技术来实现迪米特原则。然而,过分追求迪米特原则可能导致设计过于复杂,增加不必要的抽象层和中介者。因此,在使用迪米特原则时应适度应用,结合其他设计原则,关注实际场景,避免盲目追求理论上的完美设计。


http://www.kler.cn/a/417018.html

相关文章:

  • 棱光PDF工具箱:一站式解决你的各种需要
  • 【网络安全】服务器安装Docker及拉取镜像教程
  • 防御综合实验
  • 工业相机在工业生产制造过程中的视觉检测技术应用
  • 大模型推理——MLA实现方案
  • kafka生产者之发送模式与ACK
  • C++之虚基类
  • 循环神经网络(RNN)简述
  • 大R玩家流失预测在休闲社交游戏中的应用
  • Android 系统之Init进程分析
  • 【Spring MVC】关于Spring MVC编程中前后端交互实现简单登录跳转和留言板实例
  • DAY139权限提升-Linux系统权限提升篇Vulnhub辅助项目SUID权限SUDO指令版本漏洞
  • Linux系统盘的空间规划与内容存放指南
  • IDEA Services窗口不显示多服务启动类,添加类型也不存在spring boot
  • 【机器学习】机器学习学习笔记 - 监督学习 - KNN线性回归岭回归 - 02
  • electron-updater软件自动检测更新 +无服务器本地测试
  • Spark优化--开发调优、资源调优、数据倾斜调优和shuffle调优等
  • 如何使用ST7789展现图片?[ESP--4]
  • 中国剩余定理——acwing
  • windows中idea选择bash作为控制台指令集,但是系统环境变量未在其中生效处理
  • Vue 2.0->3.0学习笔记(Vue 3 (一)- 创建Vue3.0工程)
  • 白鹿 Hands-on:消除冷启动——基于 Amazon Lambda SnapStart 轻松打造 Serverless Web 应用(二)
  • 《FRAPPE: fast rank approximation with explainable features for tensors》中文校对版
  • 技术分析模板
  • 【rust】前端开发中的应用与前景
  • 安卓延迟自动点击