设计模式之六大设计原则之《五》羞涩的迪米特法则

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013821237/article/details/84393097

参考书籍:设计模式之禅--秦小波

上篇回顾:上篇讲到了接口隔离原则(ISP),讲的不好还请见谅。上篇文末留下了一个问题:“如果接口隔离原则和单一职责原则发生了冲突,鱼和熊掌如何取舍?”我们知道单一职责原则是站在业务的角度,接口隔离原则是站在接口功能定义角度。细分接口功能,很容易将一个完整的业务功能分割开来。这个时候我们切记:坚持单一职责原则!为什么呢?上篇说到,接口隔离原则细分的度没有统一的标准,过度细分会导致系统复杂度的增加,鉴于此,在业务体和接口细分产生冲突时,要优先保证单一职责原则。

迪米特法则:迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge
Principle,LKP),虽然名字不同,但描述的是同一个规则。第二个名字表述的更加直白:一个类具体是怎么执行业务的我不需要知道,你只要告诉我调用那个方法就可以了。怎样才算是告诉我有哪些方法?没错,public。类的所有public 方法和变量都认为是对我公开的。也就是说:一个类对象,应该对其他的类对象的方法、变量知道的越少越好(对外开放的public类型的方法和变量应该越少越好)。

如何理解迪米特法则?我们分为3个方面来理解:

1.不要出现不相关的类依赖

什么意思?就是说,如果这个类的出现对我没什么用处,那么不要引入进来,go anywhere they want。大家可能会说,不用的类我们怎么会引用呢,但其实这个地方非常容易忽略,我们以下面老板和秘书出差的故事为例:

老板和秘书要出远门,出远门当然要先买机票,这个时候秘书就该上场啦:

class Boss{

    //让秘书去买票
    public void ask(){
        Ticket ticket=new Ticket();
        Secretary s=new Secretary();
        s.buyTicket(ticket);   
    }
}

//秘书
class Secretary{
    public void buyTicket(Ticket ticket)
    {
            ticket.user="Jack Ma";
    }        
    
}

class Ticket{
    private String price;
    private String user;
    
    ......
        
}

上面的Boss让秘书买票,秘书(Secretary)买票,先找到了航班,然后买了老板的票。这个过程中,Boss类中出现了Ticket(机票)类,这个合理吗?按照事物的执行逻辑,确实需要用到秘书,用到机票,才能完成购票的过程。但是买票是秘书要做的事情,老板并不应该知晓具体过程,也无需了解执行的过程。我们再从代码的设计角度看这个问题,如果我们后期修改了Ticket的业务逻辑,那我们免不了要检查所有依赖Ticket类的类,对修改造成的风险进行评估。最最主要的是,车票变了,老板无需关注,这是秘书应该关心的事情,对吗?

我们作如下修改:

class Boss{

    //让秘书去买票
    public void ask(){
        Secretary s=new Secretary();
        s.buyTicket();   
    }
}

//秘书
class Secretary{
    public void buyTicket()
    {
            Ticket ticket=new Ticket();//车票被秘书私有-陈奕迅
            ticket.user="Jack Ma";
    }        
    
}

class Ticket{
    private String price;
    private String user;
    
    ......
        
}

这样是不是就没有了刚刚的担忧,Ticket的只和秘书有关系,现在老板终于可以安枕无忧了。

2.尽量不要过度了解依赖的类

我们常说亲密有间,意思是,对一个人了解的太多,就会遇到更多的烦恼,适当的距离可以产生美。上面说老板和秘书要出差,需要安排行程,我们假设公司里有两个实习的秘书:

class Boss{
    //让秘书A准备出差行程
    SecretaryA a=new SecretaryA();
    a.buyTicket();
    a.prepareHotel();
    a.prepareFood();
    a.preareMeeting();

    //让秘书B准备出差行程
    SecretaryB b=new SecretaryB();
    b.prepare();
}

//秘书A
class SecretaryA{
   public void buyTicket(){}
   public void prepareHotel(){}
   public void prepareFood(){}
   public void preareMeeting(){}
    
}
//秘书B
class SecretaryB{
   private void buyTicket(){}
   private void prepareHotel(){}
   private void prepareFood(){}
   private void preareMeeting(){}  
   
   public prepare(){
        buyTicket();
        prepareHotel();
        prepareFood();
        preareMeeting();
   }    
    
}

如果老板是你,你会欣赏哪个秘书?相信大家遇到秘书A一定会默默流泪,我要这个秘书有何用,所有的事情都需要我亲自过问,反观秘书B,你只需要说一句:安排下行程,剩下的统统不用管了,逍遥快活,也是一匹沙漠骆驼。上面的例子告诉我们,不要过多的使用public,做一个羞涩的类,把自己的事情放在心底,只让自己知道(多使用private)。

3.如何决定方法的去留

在实际应用中经常会出现这样一个方法:放在本类中也可以,放在其他类中也没有错,
那怎么去衡量呢?你可以坚持这样一个原则:如果一个方法放在本类中,既不增加类间关
系,也对本类不产生负面影响,那就放置在本类中。

总结:迪米特法则的核心思想就是:解耦!解耦!解耦!不需要的坚决不要,不相关的坚决不了解,这样,类将会更加单纯,更加原子,更加可扩展。

每篇一问:

迪米特法则让类之间联系更加独立,这可能导致两个类之间要想访问需要跨过好几层关系,那么怎么判断是否需要继续解耦呢?

猜你喜欢

转载自blog.csdn.net/u013821237/article/details/84393097