??? The Law of
Demeter和 Principle of Least
Knowledge讲的都是一回事,是说一个软件实体要尽可能的只与和它最近的实体进行通讯。通常被表述为:talk only to your immediate friends
( 只和离你最近的朋友进行交互)。?
?? “talk”,其实就是对象间方法的调用。这条规则表明了对象间方法调用的原则:
上面的方法中station对象是immediate friends。但是上面的代码却从station对象中返回了一个Thermometer对象,然后调用了thermometer对象的getTemperature()方法,违反了Principle of Least Knowledge。
?
?? “talk”,其实就是对象间方法的调用。这条规则表明了对象间方法调用的原则:
(1)?????? 调用对象本身的方法;
(2)?????? 调用通过参数传入的对象的方法;
(3)?????? 在方法中创建的对象的方法;
(4)?????? 所包含对象的方法。
上面的4点看起来有点别扭,下面通过一个具体的例子,就可以对上述4条guideline有进一步感性的认识:
?1?public?class?Car?{
?2???Engine?engine;
?3???
?4???public?Car()?{
?5?????//initialize?engine,etc.
?6?}
?7?
?8?public?void?start(Key?key)?{
?9???Doors?doors?=?new?Doors();
10???boolean?authorized?=?key.turns();
11???
12???if(authorized)?{
13?????engine.start();
14?????updateDashboardDisplay();
15?????doors.lock();
16?}
17?
18?public?void?updateDashboardDisplay()?{
19???//update?display
20}
21
22?}
?2???Engine?engine;
?3???
?4???public?Car()?{
?5?????//initialize?engine,etc.
?6?}
?7?
?8?public?void?start(Key?key)?{
?9???Doors?doors?=?new?Doors();
10???boolean?authorized?=?key.turns();
11???
12???if(authorized)?{
13?????engine.start();
14?????updateDashboardDisplay();
15?????doors.lock();
16?}
17?
18?public?void?updateDashboardDisplay()?{
19???//update?display
20}
21
22?}
下面对start()方法中的语句进行分析:
第10行-key.turns():符合上述的第(2)条,key对象是通过参数传入start()方法的。
第13行-engine.start():符合上述的第(4)条,engine对象是包含在Car的对象之中的。
第14行-UpdateDashboardDisplay():符合上述的第(1)条,UpdateDashboardDisplay()方法是Car对像自身的方法。
第15行-doors.lock():符合上述的第(3)条,doors对象是在start()方法中创建的对象。
接下来看一个违反Principle of Least Knowledge的例子:
1?public?float?getTemp()?{
2???Thermometer?thermometer?=?station.getThermometer();
3???return?thermometer.getTemperature();
4?}
2???Thermometer?thermometer?=?station.getThermometer();
3???return?thermometer.getTemperature();
4?}
上面的方法中station对象是immediate friends。但是上面的代码却从station对象中返回了一个Thermometer对象,然后调用了thermometer对象的getTemperature()方法,违反了Principle of Least Knowledge。
下面对上面的方法作出符合Principle of Least Knowledge的改进:
1?public?float?getTemp()?{
2???return?station.?getTemperature();
3?}
2???return?station.?getTemperature();
3?}
我们在Station类中添加一个方法getTemperature()。这个方法将调用Station类中含有的Thermometer对象的getTemperature()。这样getTemp()方法就只知道Station对象而不知道Thermometer对象。
总结:笛米特法则告诉我们要尽量只和离自己最近的对象进行交互。离自己最近的对象包括:自身包含的对象,方法中创建的对象,通过参数传进的对象,还有自己本身。?