前置知识
- 了解单一职责原则
- 了解接口隔离原则
- 了解封装特性
前言
本文是讲述 六大设计原则 的最后一篇,为大家讲述 迪米特原则
迪米特原则的英文释义如下
Each unit should have only limited knowledge about other units: only units “closely” related to the current unit. Or: Each unit should only talk to its friends; Don’t talk to strangers.
翻译出来,有点拗口,我们可以直接看百度的释义
迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。
总结出来就是:不该有直接依赖关系的模块不要有依赖。有依赖关系的模块之间,尽量只依赖必要的接口。
这个原则和单一职责原则类似,也和接口隔离原则类似。
下面为大家简述迪米特原则的重点,以及与其他原则的不同所在
如何用好迪米特原则
我们总结的迪米特原则有两句话,事实上分别把这两句话用好,就可以用好迪米特原则了。
第一句话是:不该有直接依赖关系的模块不要有依赖
对于这一句话,我们需要分析大致有哪几种无需依赖关系的情况,我们却使用了依赖。
- A类需要B类相关的某些属性,却把B类全部传入
- 从业务含义上,A类无需依赖B类,只是依赖其它类的时候,借助了B类做一个工具
- 业务上,A需要依赖B的函数,但无需依赖属性
以上的两种情况,都是依赖了无直接关系模块,就是违背了迪米特原则。那我们要遵循好原则的第一句话,即把对应的错误情况解决即可。
- 对于第一个错误,我们将传入的参数修改为对应的属性即可。
- 第二个错误,我们借助其他例如工厂模式,让工厂类依赖B类,使用工程类创建好A类即可。
- 而第三个错误,处理得很简单,把属性私有化即可,如此依赖B的时候,也就不会无意间调用到属性了。可见封装的特性也是迪米特原则的关键。
当然,违反迪米特原则的问题还有很多,我们需要善于 review 我们的代码,将违反对应原则的代码找出来,修复即可。
第二句话:有依赖关系的模块之间,尽量只依赖必要的接口
当模块之间,类之间确切有业务依赖关系的时候,最好只依赖当前需要的接口。我们在前文 继承和组合如何选择|设计模式基础 中有使用 组合+接口+委托 的方式让子类只依赖自身需要依赖的接口;在 接口隔离原则|设计原则 中,也把多余的接口独立开来。
本文继续引用 组合 一文中的demo,为大家展示如何减少不必要的依赖。
具体代码如下(From:《设计模式之美》):
public interface Flyable { void fly(); } public class FlyAbility implements Flyable { @Override public void fly() { //... } } //省略Tweetable/TweetAbility/EggLayable/EggLayAbility public class Ostrich implements Tweetable, EggLayable {//鸵鸟 private TweetAbility tweetAbility = new TweetAbility(); //组合 private EggLayAbility eggLayAbility = new EggLayAbility(); //组合 //... 省略其他属性和方法... @Override public void tweet() { tweetAbility.tweet(); // 委托 } @Override public void layEgg() { eggLayAbility.layEgg(); // 委托 } } 复制代码
当上述的 Ostrich 只需依赖 Tweetable
和 EggLayable
两个接口的时候,我们就只继承这两个接口,当然,前提是我们要把接口颗粒度降低、细化。
迪米特原则与其他原则的不同
迪米特原则与单一职责原则
迪米特注重 调用类与被调用类 之间的关系,主要让两者的联系最小,其重于实现低耦合;而单一职责更关系本身是否功能单一、涉及的业务单一,其重于实现高内聚。
迪米特原则与接口隔离原则
迪米特原则与接口隔离原则之间,有两点的不同,一是涉及的范围不同,二是目的不同。
范围不同
迪米特原则的范围包括类,属性,接口等,所有拥有依赖关系的都涉及到迪米特原则。
而接口隔离原则只涉及到接口,要求接口符合单一即可。
目的不同
迪米特原则的目的是:让依赖的模块间低耦合,其涉及初衷就是降低模块间的关联。
而接口隔离原则的目的是:让接口功能单一,以提升复用性和拓展性。这也间接的使得模块间变得低耦合。