设计模式 之 迪米特法则

设计模式系列文章:
设计模式 之 设计原则(1) 单一职责原则 接口隔离原则 依赖倒转原则
面向对象 之 不能不知道的类间关系(上)泛化、实现、依赖 C++与Java
面向对象 之 不能不知道的类间关系(下)关联、聚合、组合 C++与Java
JAVA单例模式分析及其实现:饿汉式、懒汉式、双重检查、静态内部类


迪米特法则

迪米特法则,又叫做最少知道原则。

我们先来看一下这个法则的定义:

迪米特法则:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。
    	如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

读起来朗朗上口,读完后一脸懵逼。单单从这个定义来看确实很难 get 到这个法则的精髓。

那就不妨先来看一下,迪米特法则等另一种更通俗的表述方式:只于直接的朋友通信
直接的朋友指的是在类中的作为成员变量、方法参数或者方法返回值的类。而在方法内部出现的类就不是直接的朋友。换句话说,应该避免在一个方法体中实例化陌生类的成员并使用它的方法。
那么当需要使用到这个陌生类的方法的时候,应该让它以直接的朋友身份出现或者通过直接的朋友调用这个方法。

我们来举一个粟子:
在周朝分封制的背景下,社会等级有着严格的划分,每个阶级只与紧挨着它的上面和下面的阶级产生联系。跨级的管理是不被允许的。引用度娘上找到的的图片:
在这里插入图片描述
这样的背景可以很好地体现迪米特法则,让我们从士的角度来看,对于使来说,“直接的朋友”下级 平民,士是不可以直接命令奴隶的。如果一个士希望完成自己土地上庄稼的收割,而收割这个行为只能由奴隶来完成。那么士直接使用奴隶来完成收割是不合理的,违背了迪米特法则。

违背迪米特法则的设计:

在这里插入图片描述

class Shi
{
	private Civilian civilian;
	public void harvest()
	{
		Slave slave = new Slave();
		slave.harvest();
	}
}
class Civilian 
{
	private Slave slave;
	.
	.
}
class Slave 
{
	public void harvest()
	{
		System.out.println("收割庄稼ing~");
	}
}

这里士这个类就出现了在方法中使用陌生类的违背迪米特法则的情况,导致设计出的类间耦合度很高并不利于维护。
分析后可知,奴隶类与士类是不需要发生直接关联的,具有直接关联的,是士与平民。因此正确的逻辑应该是士命令属下平民进行收割而平民命令奴隶进行收割。

改进后的设计:

在这里插入图片描述

class Shi
{
	private Civilian civilian;
	public void harvest()
	{
		civilian.harvest();
	}
}
class Civilian 
{
	private Slave slave;
	public void harvest()
	{
		slave.harvest()
	}
}
class Slave 
{
	public void harvest()
	{
		System.out.println("收割庄稼ing~");
	}
}

需要注意的是,迪米特法则 首先强调的前提 是在类的结构设计上,每一个类都应单尽量降低成员的访问权限,对不需要公开的字段或者方法进行封装,留下需要向外界公开的接口(不是狭义上的 interface接口,而是泛指一种使用范式)。
对于上面的例子来说,仅归属于自己的成员就是不能公开的,而收割这个行为是对外公开的。

接着对于一开始给出的定义,我们就可以进一步的阐述了。

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。

刚刚提到了 直接的朋友 这个概念,不是直接的朋友类,彼此间就处于不必进行直接通信的状态。在方法中实例并使用陌生类的对象就是一种相互作用。

如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用

对于这句话理解的难点在于这个 第三者 。如果仅仅是实例一个新的陌生类对象作为第三者用来转发这个调用的话,仍然是违背迪米特法则的,非但没有降低程序的耦合,反而增加了程序出错的可能性。
因此,这个第三者,就应当是类直接的朋友 。
本质上,是使用已经存在的关联关系来消除与陌生类之间的依赖,进而降低类间的耦合度。


系列文章参考资料:

  • 图解Java设计模式 视频很全也很棒,墙裂推荐。视频就在站内。
  • 《设计模式》 设计模式的经典。
  • 《大话设计模式》非常有名的小白友好型设计模式著作

猜你喜欢

转载自blog.csdn.net/wayne_lee_lwc/article/details/105575233