面向对象六大原则(六):迪米特原则

一、概述

迪米特原则( Law of Demeter  ,缩写:LoD),又叫作最少知识原则(Least Knowledge Principle,简写LKP),就是说一个对象应当对其他对象有尽可能少的了解。

二、原则

一个类应该对自己需要耦合或调用的类知道的最少,类的内部如何实现与调用者或者依赖者没关系,调用者或者依赖者只需要知道它需要的方法即可,其他的可一概不用管。类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。

迪米特法则可以简单说成:talk only to your immediate friends.也就是“只与直接的朋友通信”。至于什么是直接的朋友?每个对象都必然会与其它对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系的类型有很多,如组合、聚合、依赖等。 

三、举例说明

下面引用《Android源码设计模式解析与实战》一书中示例:

1.只要求房间的面积和租金,其他一概不管,中介将符合我要求的房子提供给我就可以,如下代码:

    /*
    * 房间
    * */
    public class Room{
        public float area;
        public float price;
        public  Room(float area, float price){
            this.area = area;
            this.price = price;
        }

        @Override
        public String toString() {
            return "Room [area="+area+",price="+price+"]";
        }
    }

    /*
    * 中介
    * */
    public class Mediator{
        List<Room> mRooms = new ArrayList<Room>();

        public Mediator(){
            for (int i=0;i<5;i++){
                mRooms.add(new Room(14+i,(14+i)*150));
            }
        }

        public List<Room> getAllRooms(){
            return mRooms;
        }
    }
    
    /*
    * 租户
    * */
    public class Tenant{
        public float roomArea;
        public float roomPrice;
        public static final float diffPrice = 100.0001f;
        public static final float diffArea = 0.00001f;
        
        public void rentRoom(Mediator mediator){
            List<Room> rooms = mediator.getAllRooms();
            for (Room room:rooms){
                if(isSuitable(room)) {
                    System.out.println("租到房啦!" + room);
                    break;
                }
            }
        }
        
        private boolean isSuitable(Room room){
            return Math.abs(room.price - roomPrice) < diffPrice
                    &&Math.abs(room.area = roomArea) < diffArea;
        }
    }

2.从上述代码可看到,Tenant不仅依赖了Mediator类,还需要频繁地与Room类打交道,导致Tenant与Room的耦合较高,所以需要解耦。首先明确的是我们只和我们的朋友通信,这里指Mediator对象,必须将Room相关的操作从Tenant中移除,至此我们重构代码如下:

    /*
    * 房间
    * */
    public class Room{
        public float area;
        public float price;
        public  Room(float area, float price){
            this.area = area;
            this.price = price;
        }

        @Override
        public String toString() {
            return "Room [area="+area+",price="+price+"]";
        }
    }

    /*
    * 中介
    * */
    public class Mediator{
        List<Room> mRooms = new ArrayList<Room>();

        public Mediator(){
            for (int i=0;i<5;i++){
                mRooms.add(new Room(14+i,(14+i)*150));
            }
        }

        public Room rentOut(float area, float price){
            for (Room room : mRooms){
                if (isSuitable(area , price ,room)){
                    return room;
                }
            }
            
            return null;
        }

        private boolean isSuitable(float area, float price, Room room){
            return Math.abs(room.price - price) < Tenant.diffPrice
                    &&Math.abs(room.area = area) < Tenant.diffArea;
        }
    }

    /*
    * 租户
    * */
    public class Tenant{
        public float roomArea;
        public float roomPrice;
        public static final float diffPrice = 100.0001f;
        public static final float diffArea = 0.00001f;

        public void rentRoom(Mediator mediator){
            System.out.print("租到房啦!"+mediator.rentOut(roomArea,roomPrice));
        }

        
    }

只是将对于Room的判定操作移到了Mediator类中,这本应该是Mediator的职责,根据租户设定的条件查找符合要求的房子,并且将结果交给租户就可以了。租户并不需要知道太多关于Room的细节,比如与房东签合同、设施坏了找谁维修等。当我们通过我们的“朋友”--中介 租了房后,所有的事情我们都通过与中介沟通就好了,房东、维修师傅等角色都并不是我们直接的“朋友”。

“只与直接的朋友通信”这就足够将我们从复杂的关系网中抽离出来,使程序耦合度更低、稳定性更好。

四、分析

迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。

迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系--这在一定程度上增加了系统的复杂度。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值