面向对象的六大原则(六)

迪米特原则的定义

迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP),虽然名字不同,但描述的是同一个规则:(一个对象应该对其他对象有最少的了解)。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心。

总结起来就是以下三点:

  • Each unit should have only limited knowledge about other units: only units “closely” related to the current unit.(每个单元对于其他的单元只能拥有有限的知识:只是与当前单元紧密联系的单元。)
  • Each unit should only talk to its friends; don’t talk to strangers.(每个单元只能和它的朋友交谈:不能和陌生单元交谈。)
  • Only talk to your immediate friends.(只和自己直接的朋友交谈。)

迪米特原则的示例

先来看这样的一个应用场景,我们现在的服务器允许用户来连接,当用户连接上并且认证通过后,它们就被包装在User类中。

1
2
3
4
5
6
7
8
9
10
11
public class User {
public String userName;
public int id;
public Socket socket;
public void disconnect() throws Exception {
socket.close();
}
// 其它处理socket的方法
}

我们要发送一条消息给用户,我们创建一个Message类:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Message {
//给用户发送"Hello..."消息
public void sayHello(User user) {
Socket s = user.socket;
try {
OutputStream outputStream = s.getOutputStream();
PrintWriter out = new PrintWriter(outputStream);
out.println("Hello...");
} catch (Exception e) {
//处理异常
}
}
}

这样的设计有没有问题呢,User类没有很好地把socket对象封装起来,并且将它暴露给了Message类。这样一来,如果我们以后想修改实现(比如使用一个异步的socket库),我们就得在很多地方做修改。
除此之外,Message类中的sayHello()方法也有问题,直接与socket对象进行交互,它能访问一个第三方的对象(socket)并且直接使用,这样的设计当然是不合理的,它违背了迪米特原则中的第二条,与陌生单元直接进行了交流。那么我们现在修改一下
首先把User类的内部细节隐藏起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class User {
public String userName;
public int id;
//首先把域变成私有的,对外隐藏socket细节
private Socket socket;
public void sendMessage(String message) {
try {
OutputStream outputStream = socket.getOutputStream();
PrintWriter out = new PrintWriter(outputStream);
out.println(message);
} catch (Exception e) {
//处理异常
}
}
// 其它处理socket的方法...
public void disconnect() throws Exception {
socket.close();
}
}

接下来修改Message类中的sayHello()方法

1
2
3
4
5
public class Message {
public void sayHello(User user) {
user.sendMessage("Hello...");
}
}

这样一来socket就对sayHello()方法完全不可见了,这样的设计就变得更健壮了。

迪米特原则的实践

迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度。在采用迪米特法则时需要反复权衡,既做到让结构清晰,又做到高内聚低耦合。

参考代码

------ 本文结束 ------

版权声明


BillyYccc's blog by Billy Yuan is licensed under a Creative Commons BY-NC-SA 4.0 International License.
本文原创于BillyYccc's Blog,转载请注明原作者及出处!