当前位置 : 主页 > 编程语言 > 其它开发 >

设计模式七大原则—迪米特法则

来源:互联网 收集:自由互联 发布时间:2022-05-30
1.概念 1.1.知道的越少越好 迪米特法则,结合其含义又称之为“最少知道原则”, 即一个类作为一个调用方,应当对自己依赖的类(被调用的类)其中所处理的逻辑细节,知道的越少越好
1.概念 1.1.知道的越少越好

迪米特法则,结合其含义又称之为“最少知道原则”,即一个类作为一个调用方,应当对自己依赖的类(被调用的类)其中所处理的逻辑细节,知道的越少越好。对于被依赖的类(被调用的类)不管在使用上多么的复杂,它都应尽量将处理逻辑封装在它的内部,对调用方提供简洁明了的公共方法即可,以此减轻上层调用方过多承担复杂逻辑的压力和变化。

1.2.朋友和陌生人

对于程序编码设计是否遵循了“迪米特法则”,我们通常可以使用一段经典的描述来判断,该描述是:“只和朋友通信,不和陌生人说话”。那么对于这段话中什么是朋友,什么是陌生人,下面对其进行一个介绍。

每个对象都会与其他对象之间都存在一定程度的耦合关系,其中主要耦合方式包含:依赖、关联、组合、聚合等等。如果某个类作为被调用者,在其调用方的类中的内部主要体现为:类中成员变量的类型、方法参数类型、方法返回值类型,那么该类就属于调用者的“朋友”。

对于某个类而言,当它作为“被调用者”在“调用者”当中没有作为:类中成员变量的类型、方法参数类型、方法返回值类型,这些形式出现在类中,而是仅作为局部变量出现在某个方法体中,那么对于这种情况,该类就属于“陌生人”。

1.3.高内聚低耦合

如果类在编写时产生了大量与“陌生人说话”,那么这样会导致依赖的类具有隐匿性,如果“陌生人”发生改动,那么其他使用“陌生人”的类(调用方)很难精确的做出协调,需要改动的地方也很难预估,这样就加剧了类与类之间的耦合程度,你很难断绝对某个类的依赖。

另外,本来处理逻辑是类自己内部可以处理的,如果非要将处理逻辑带到上层(调用方),这样就导致上层(调用方)违背了“最少知道原则”,并且不符合高内聚(自己的事情自己做)。

由此可见,迪米特法则的核心思想就是让编码设计实现:高内聚,低耦合。


2.举例

我们的程序最终要想实现迪米特法则”,其实就是遵循“最少知道原则”,具体实现这个原则就要程序做到“只和朋友通信,不和陌生人说话”。这些介绍在理解层面上都是相对抽象的,接下来我将通过生活中的例子和代码来更通俗的体会迪米特法则。

 

2.1.生活场景

在实际的生活当中,人们都可以通过点外卖的方式来解决自己用餐的需求,接下来我将以点外卖解决用餐需求作为背景,来类比“迪米特法则”中的概念。

张三心血来潮突然想吃“全聚德”的菜肴,但是他又不想出门走上几公里的路去门店吃。于是他在网上查找发现了“全聚德”刚刚开设的外送模式,他哽咽着口水赶忙的打电话预定了外送订单。

由于“全聚德”在外送模式下刚刚开设还在起步阶段,有些外送门路还不是很了解,全聚德一开始将外送员、厨师、食材一起带到张三家,在张三家现场制作菜肴。在家中现场制作的过程中经常发生一些问题:张三在看到制作流程后经常会指手画脚导致味道“四不像”、厨师由于身体情况做了几道菜后就经常去拉肚子导致糊锅。

这些问题导致了张三并没有享受到了外送模式的便捷,因为当前的外送模式,全聚德让张三知道了太多的菜肴制作细节并且于过多的人产生联系,对于这个场景参照到“迪米特法则”来说,就是没有让使用方(张三)遵循“最少知道原则”,让使用者过多知道一些细节,从而增加了复杂程度。

另外在外送模式下,全聚德让过多的人员参与到了外送当中,其中有外送员、厨师、食材。其实张三作为顾客并不用和厨师、食材打交道,这样只会增加用餐的依赖程度,张三其实只用和餐馆的外送员打交道即可。那么这里的场景参照到“迪米特法则”当中,对于外送员而言和张三就是“朋友”,厨师、食材是“陌生人”,上面的例子中,厨师在现场制作菜肴经常因为身体情况拉肚子,就是体现出依赖了“陌生关系”,从而增加了耦合度并因此带来不可预估的风险。

“全聚德”为了实现更好的外卖用餐体验,使用迪米特法则对外送模式进行改良,之后的张三在不用关心更多的菜肴制作细节和对厨师的依赖,他只用接到外送员外送的菜肴,就可以快捷的享受到美食。

 

2.2.代码案例

在通过生活场景和迪米特法则概念进行类比后,我们接着这个例子通过代码案例在加深对迪米特法则的理解,以及使用它的好处。代码案例有两种形式,一种是没有遵循迪米特法则的例子,另一个是遵循了迪米特法则的例子,后者是针对前者存在问题改进,通过对比的形式更能突出该原则的优势。

 未使用迪米特法则

 1     class Person
 2     {
 3 
 4         public void 点外卖(外送员 foodDelivery,string 菜名)
 5         {
 6             厨师 张大师= foodDelivery.通知餐馆安排人员制作菜肴();
 7             var 菜肴=  张大师.烹饪(菜名);
 8 
 9             foodDelivery.送餐(菜肴);
10 
11             Console.WriteLine($"送餐成功,开始吃{菜肴}");
12 
13         }
14     }
15 
16     class 外送员 
17     {
18         public 厨师 通知餐馆安排人员制作菜肴()
19         {
20             return new 厨师();
21         }
22         public string 送餐(string 菜肴)
23         {
24             Console.WriteLine("根据路线进行送餐");
25             return 菜肴;
26         }
27     }
28 
29     class 厨师
30     {
31         public string 烹饪(string 菜名)
32         {
33             Console.WriteLine("烹饪制作");
34             return 菜名;
35         }
36     }

我们主要看Person类中的代码,Person类在当前代码中作为一个调用者(使用方),在点外卖的方法中使用到了两个类,一个是外送员类和厨师类。那么基于本文中对“朋友与陌生人”的概念,此时的朋友其实就是外送员类,因为它作为一个方法的参数类型包含在类中,是符合朋友的标准。对于厨师类而言就是陌生人,因为它作为局部变量在类的方法中,那么对于以上代码很显然就违反了迪米特法则。

 

使用迪米特法则

 1     class Person
 2     {
 3 
 4         public void 点外卖(外送员 foodDelivery,string 菜名)
 5         {          
 6           var 菜肴= foodDelivery.送餐(菜名);
 7             Console.WriteLine($"送餐成功,开始吃{菜肴}");
 8         }
 9     }
10 
11     class 外送员 
12     {
13         public 厨师 通知餐馆安排人员制作菜肴()
14         {
15             return new 厨师();
16         }
17         public string 送餐(string 菜名)
18         {
19             var 菜肴 =  通知餐馆安排人员制作菜肴().烹饪(菜名);
20            
21             Console.WriteLine("根据路线进行送餐");
22             return 菜肴;
23         }
24     }
25 
26     class 厨师
27     {
28         public string 烹饪(string 菜名)
29         {
30             Console.WriteLine("烹饪制作");
31             return 菜名;
32         }
33     }

通常作为顾客并不关心菜肴的制作过程或外送员送餐的路线,他只关心外送员能够在预期时间进行送餐,使他能吃上饭。所以该代码案例主要将菜肴的制作环节从Person类中取掉,将菜肴的制作推向外部,这样就做到了让Person类遵循“最少知道原则”,另外切断点外卖方法中与厨师类(陌生人)的联系,促使Person类只和“朋友通信”(外送员),这样就实现了迪米特法则。


3.补充

类与类之间的耦合是不可避免的,遵循迪米特法则并不是完全解除依赖,而是在一定程度上降低类与类之间不必要的依赖。例如其中的某个概念:“不和陌生人说话”,这就并不是一个能够完全杜绝的情况,我们只能尽量的不要让陌生的类作为局部变量出现在类的内部,并且保障类对自己依赖的类知道的越少越好。

这从侧面也反映了设计模式原则并不是一个教条,而必须遵守,作为编码者更重要的是提炼其中的思想,根据实际的情况尽量的让程序设计做到最大化的“高内聚,低耦合”。

知识改变命运 【文章原创作者:武汉网站优化公司 http://www.5h5q.com/wzyh/ 复制请保留原URL】
网友评论