java设计模式6大设计原则之迪米特法则原则

本文介绍了迪米特法则,也称为最少知道原则,强调在软件设计中减少类之间的耦合。通过一个学生、老师和校长的模拟场景,展示了违背和遵循迪米特法则的代码实现。当校长直接管理学生信息时,代码耦合度高,不符合迪米特法则。改进后的设计中,校长只与老师交互,老师负责处理学生信息,从而降低了耦合,提高了代码的可读性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

迪米特原则

1.1 迪米特法则定义

迪米特法则又称为最少知道原则,也就是说一个对象类对其他对象来说,知道的越少越好,两个类之间不要有过多的耦合关系,保持最少关联性。
迪米特法则有一句经典语录:只和朋友通信,不和陌生人说话。也就是说有关联的内要内聚,没有直接关系的类要低耦合。

2.1 模拟场景

通过模拟学生、老师、校长之间的关系来模拟迪米特法则。老师负责具体某一个学生的学习情况,而校长只会关系每个班级的总体成绩,不会具体过问某一个学生的具体成绩。
如果校长想要知道一个班级的总体成绩是直接找每个学生要再进行统计呢,还是应该向老师要呢?显然应该是直接向老师要一个班级的总体成绩。我们在实际开发,容易忽略这样的真实情况,开发出逻辑错误的程序。

2.2 违背原则方案

首先定义一个学生类,主要有学生姓名、考试排名、总分。

public class Student {
    private String name; //学生姓名
    private int rank;   //考试排名
    private double grade;   //总分

    public Student() {
    }

    public Student(String name, int rank, double grade) {
        this.name = name;
        this.rank = rank;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getRank() {
        return rank;
    }

    public void setRank(int rank) {
        this.rank = rank;
    }

    public double getGrade() {
        return grade;
    }

    public void setGrade(double grade) {
        this.grade = grade;
    }
}

之后再定义出老师类,在老师类中初始化学生信息,以及提供基本信息获取接口

public class Teacher {
    private String name;    //老师姓名
    private String clazz;   //班级
    private static List<Student> studentList; //学生人数

    public Teacher() {
    }

    public Teacher(String name, String clazz) {
        this.name = name;
        this.clazz = clazz;
    }

    static {
        studentList=new ArrayList<>();
        studentList.add(new Student("小明",10,450));
        studentList.add(new Student("花花",4,553));
        studentList.add(new Student("小明",18,354));
        studentList.add(new Student("小明",7,581));
        studentList.add(new Student("小明",20,300));
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public static List<Student> getStudentList() {
        return studentList;
    }

    public static void setStudentList(List<Student> studentList) {
        Teacher.studentList = studentList;
    }
}

在老师类中初始化了学生信息,同时提供了简单的接口。下面定义校长类,校长管理全局,并在校长类中获取学生人数、总分、平均分等。

public class Principal {
    private Teacher teacher = new Teacher("王丽", "5年级1班");

    //查询班级信息,总分、平均分、学生人数
    public Map<String, Object> queryClazzInfo(String clazzId) {
        //获取学生人数
        int stuCount = clazzStudentCount();
        //获取平均分
        double averageScore = clazzAverageScore();
        //获取总分
        double totalScore = clazzTotalScore();
        //组装对象
        Map<String, Object> map = new HashMap<>();
        map.put("老师", teacher.getName());
        map.put("班级", teacher.getClazz());
        map.put("人数", stuCount);
        map.put("平均分", averageScore);
        map.put("总分", totalScore);
        return map;
    }

    //获取学生人数
    private int clazzStudentCount() {
        return teacher.getStudentList().size();
    }

    //获取班级学生总分
    public double clazzTotalScore() {
        return teacher.getStudentList()
                .stream()
                .map(Student::getGrade).mapToDouble(Double::doubleValue).sum();
    }

    public double clazzAverageScore() {
        double sum = teacher.getStudentList()
                .stream()
                .map(Student::getGrade).mapToDouble(Double::doubleValue).sum();
        return sum / teacher.getStudentList().size();
    }
}

以上就是通过校长管理所有学生,老师只提供非常简单的信息。虽然可以查看到结果,但是违背了迪米特法则,因为校长需要了解每个学生的情况。如果所有班级类都让校长类进行统计,代码就会变得非常臃肿,也不易于扩展和维护。

2.3 迪米特法则改善代码

从以上实现方式我们发现,不该让校长直接管理学生,应该老师管理学生,校长管理老师。所以应该老师类通过学生信息查询服务。下面我们把校长要的信息交给老师类去处理。

public class Teacher {
    private String name;    //老师姓名
    private String clazz;   //班级
    private static List<Student> studentList; //学生人数

    public Teacher() {
    }

    public Teacher(String name, String clazz) {
        this.name = name;
        this.clazz = clazz;
    }

    static {
        studentList=new ArrayList<>();
        studentList.add(new Student("小明",10,450));
        studentList.add(new Student("花花",4,553));
        studentList.add(new Student("小明",18,354));
        studentList.add(new Student("小明",7,581));
        studentList.add(new Student("小明",20,300));
    }
    //获取学生人数
    public int clazzStudentCount() {
        return getStudentList().size();
    }

    //获取班级学生总分
    public double clazzTotalScore() {
        return getStudentList()
                .stream()
                .map(Student::getGrade)
                .mapToDouble(Double::doubleValue).sum();
    }
    //获取平均分
    public double clazzAverageScore() {
        double sum = getStudentList()
                .stream()
                .map(Student::getGrade)
                .mapToDouble(Double::doubleValue).sum();
        return sum / getStudentList().size();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public static List<Student> getStudentList() {
        return studentList;
    }

    public static void setStudentList(List<Student> studentList) {
        Teacher.studentList = studentList;
    }
}

使用迪米特法则后,将原来违背迪米特法则的服务接口交给老师类去处理。这样每一位老师都会提供对应的功能,校长类只需要调用即可,而不需要了解每一位学生的分数。

接来看校长类如何使用,如下所示:

public class Principal {
    private Teacher teacher = new Teacher("王丽", "5年级1班");

    //查询班级信息,总分、平均分、学生人数
    public Map<String, Object> queryClazzInfo(String clazzId) {
        //获取学生人数
        int stuCount = teacher.clazzStudentCount();
        //获取平均分
        double averageScore = teacher.clazzAverageScore();
        //获取总分
        double totalScore = teacher.clazzTotalScore();
        //组装对象
        Map<String, Object> map = new HashMap<>();
        map.put("老师", teacher.getName());
        map.put("班级", teacher.getClazz());
        map.put("人数", stuCount);
        map.put("平均分", averageScore);
        map.put("总分", totalScore);
        return map;
    }
}

校长类直接调用老师类服务接口即可,这样一来整个功能逻辑就非常清晰了。

下面验证程序结果:

public class Test {
    public static void main(String[] args) {
        Principal principal = new Principal();
        Map<String, Object> map = principal.queryClazzInfo("5年级1班");
        System.out.println("查询结果:"+map);
    }
}

查询结果:{总分=2238.0, 班级=5年级1, 老师=王丽, 人数=5, 平均分=447.6}

以上就是迪米特法则的基本使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值