一、定义
最少知识原则——即迪米特法则:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。
二、理解
面向对象的程序设计中,对象与对象之间尽量相互独立,具体对象的行为由具体的对象去完成,而不是由某个对象去指定另一个对象去实施具体的行为。
通俗地讲,一个类应该对自己需要调用的类知道得最少,至于它的内部是如何复杂工作的自己不需要知道,只需知道它提供的public方法,其他的不需要去关心。
三、案例
栗子:要吃晚餐了,主人通知管家去准备晚餐,管家则安排哪位佣人去准备晚餐。
这里,主人只需要通知管家即可,而不需要自己去安排或者指挥管家去安排哪位佣人来准备晚餐。
佣人:
public class Maid {
private String maidName;
public Maid() {
super();
}
public Maid(String maidName) {
super();
this.maidName = maidName;
}
public void cook(){
System.out.println(this.maidName + ">>做饭!");
}
}
管家:
public class Butler {
public void cook(List<Maid> maidList){
for (Maid maid : maidList) {
maid.cook();
}
}
}
主人:
public class Master {
public void cookCommand(Butler butler){
List<Maid> maidList = new ArrayList<Maid>();
for(int i = 0; i < 2; i++){
maidList.add(new Maid("maid" + i));
}
butler.cook(maidList);
}
}
上面的这个设计就违背了迪米特法则,因为,Master与Butler、Maid是层级的关系,在Master这个类中,只需要去管理Butler,而Butler去管理Maid,通俗来说是Master给Butler吩咐任务,Butler接到任务后然后再给Maid分配任务。
我们按照这个思路重新设计一下上面的例子。
管家:
public class Butler {
public List<Maid> getMaidList(){
List<Maid> maidList = new ArrayList<Maid>();
for(int i = 0; i < 2; i++){
maidList.add(new Maid("maid" + i));
}
return maidList;
}
public void cook(){
List<Maid> maidList = getMaidList();
for (Maid maid : maidList) {
maid.cook();
}
}
}
主人:
public class Master {
public void cookCommand(Butler butler){
butler.cook();
}
}
这样设计的话,你会发现,Master不用跟Maid打交道,而是和Butler打交道,这样的话,减少了类与类之间不必要的耦合,使得系统更稳定,扩展更容易。
四、注意事项
- 1、在类的划分上,应当创建弱耦合的类,类与类之间的耦合越弱,就越有利于实现可复用的目标;
- 2、在类的结构设计上,每个类都应该降低成员的访问权限;
- 3、在类的设计上,只要有可能,一个类应当设计成不变的类;
- 4、在对其他类的引用上,一个对象对其他类的对象的引用应该降到最低;
- 5、尽量限制局部变量的有效范围,降低类的访问权限;
五、优缺分析
- 优点: 弱化类与类之间的耦合关系(高内聚、低耦合),弱化耦合关系可以提升复用率;
- 缺点: 因为迪米特法则要求类与类之间尽量不直接通信,如果类之间需要通信就通过第三方转发的方式,这就直接导致了系统中存在大量的中介类,会造成不同模块之间的通信效率降低,同时也大大增加了系统的复杂度,使系统的不同模块之间不容易协调;解决这个问题的方式是:使用依赖倒转原则,这样就可以使调用方和被调用方之间有了一个抽象层,被调用方在遵循抽象层的前提下就可以自由的变化,此时抽象层成了调用方的朋友。