1.背景
1987年秋天由美国Northeastern University的Ian Holland提出,被UML的创始者之一Booch等普及。后来,因为在经典著作《 The Pragmatic Programmer》而广为人知。
2.概念
迪米特法则(Law of Demeter)又叫作最少知识原则(The Least Knowledge Principle),一个类对于其他类知道的越少越好,就是说一个对象应当对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。英文简写为: LOD。
通俗的讲:
-
不该知道的不要知道;
-
一个类应该保持对其它对象最少的了解,只和朋友通信,不和陌生人说话;
-
降低类之间的耦合度;
-
从依赖者的角度来说,只依赖应该依赖的对象;
-
从被依赖者的角度说,只暴露应该暴露的方法;
设计原则:
-
在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标;
-
在类的结构设计上,尽量降低类成员的访问权限;
-
在类的设计上,优先考虑将一个类设置成不变类;
-
在对其他类的引用上,将引用其他对象的次数降到最低;
-
不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法);
-
谨慎使用序列化(Serializable)功能;
3.案例
需求:租客想通过中介找房子,租客想要一个20平、2000一个月的。
方案一(不满足迪米特原则):把所有房源都给租客,租客自己选
/// <summary>/// 房源/// </summary>public class Room{private int are;private int pay;public int getAre(){return are;}public void setAre(int are){this.are = are;}public int getPay(){return pay;}public void setPay(int pay){this.pay = pay;}}/// <summary>/// 中介/// </summary>public class Mediator{private List<Room> allRooms = new List<Room>();/// <summary>/// 初始化房源/// </summary>public Mediator(){for (int i = 0; i < 10; i++){Room room = new Room();room.setAre((i + 1) * 5);room.setPay((i % 4 == 0 ? 1 : i % 4) * 1000);allRooms.Add(room);}}/// <summary>/// 获取所有房源/// </summary>/// <returns></returns>public List<Room> GetAllRooms(){return allRooms;}}/// <summary>/// 租客/// </summary>public class Tenant{public static void RentRoom(Mediator mediator){// 通过中介获取所有房屋List<Room> allRoom = mediator.GetAllRooms();foreach(Room room in allRoom){if (IsSuitable(room)){Console.WriteLine("房屋找到了");}}}/// <summary>/// 判断房子是否满足客户需求/// </summary>/// <param name="room"></param>/// <returns></returns>private static bool IsSuitable(Room room){// 筛选房屋return true;}}{//LOD:迪米特原则Tenant.RentRoom(new Mediator());}
代码分析:
以上的方案是中介直接把所有的房源全部提供给顾客,其中就包含不满足租客条件的房源,这就增加了租客和房源直接的耦合度。
方案二(满足迪米特原则):先按照要求把房源筛选出来,给租客
/// <summary>/// 房源/// </summary>public class Room{private int are;private int pay;public int getAre(){return are;}public void setAre(int are){this.are = are;}public int getPay(){return pay;}public void setPay(int pay){this.pay = pay;}}/// <summary>/// 中介/// </summary>public class MediatorLOD{private List<Room> allRooms = new List<Room>();public MediatorLOD(){for (int i = 0; i < 10; i++){Room room = new Room();room.setAre((i + 1) * 5);room.setPay((i % 4 == 0 ? 1 : i % 4) * 1000);allRooms.Add(room);}}/// <summary>/// 找出符合租客要求的房子/// </summary>/// <param name="are"></param>/// <param name="pay"></param>/// <returns></returns>public Room RentRoom(int are, int pay){// 通过中介获取所有房屋foreach(Room room in allRooms){if (IsSuitable(room, are, pay)){return room;}}return null;}/// <summary>/// 判断房源是否满足客户的要求/// </summary>/// <param name="room"></param>/// <param name="are"></param>/// <param name="pay"></param>/// <returns></returns>private bool IsSuitable(Room room, int are, int pay){// 筛选房屋return true;}}/// <summary>/// 租客/// </summary>public class TenantLOD{/// <summary>/// 获取满足条件的房源/// </summary>/// <param name="mediator"></param>public static void RentRoom(MediatorLOD mediator){Console.WriteLine(mediator.RentRoom(20, 2000));}}{//LOD:迪米特原则Tenant.RentRoom(new Mediator());}
代码分析:
相比方案一,当前方案把筛选的过程放到了租客能联系到的中介身上,中介处理房源,而租客和房源的联系微乎其微,这就利用了LOD 原则,降低了租客和房源的耦合度,租客只看到符合条件的房源就可以了。
4.优缺点
优点:
-
降低了类之间的耦合度,使类与类之间保持松散的耦合关系;
-
由于耦合度降低,提高了模块的相对独立性;
-
提高类的可复用性和系统的扩展性;
缺点:
-
迪米特法则是一种面向对象系统设计风格的一种法则,尤其适合做大型复杂系统设计指导原则。但是也会造成系统的不同模块之间的通信效率降低,使系统的不同模块之间不容易协调等。