Java设计原则 - 迪米特法则

本文通过具体案例介绍了迪米特法则的基本概念及其应用场景,强调了减少类间不必要的依赖以降低耦合度的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

六大设计原则

定义

一个对象应该对其他对象保持最少的了解

迪米特法则又叫最少知道原则,只与朋友说话,不要与陌生人说话。对类而言,哪些是朋友类呢?出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类。也就是说,方法体内的局部变量最好不是陌生类。

场景

我们设计一个场景,客户的空调坏了,联系商家叫维修师傅上门维修空调:

// 工具类
public class Tool {
    public String getName() {
        return "扳手";
    }
}
// 维修师傅
public class Worker {
    public void doWork(Tool tool) {
        System.out.println("维修师傅用" + tool.getName() + "在维修空调");
    }
}
// 商家
public class Business {
    private Worker worker;
    public Business() {
        worker = new Worker();
    }
    public void command() {
        Tool tool = new Tool();
        worker.doWork(tool);
    }
}
// 客户
public class Client {
    public static void main(String[] args) {
        Business business = new Business();
        business.command();
    }
} 

我们重点分析商家类Business,它的直接朋友类是维修师傅类Worker(出现在成员变量中),可是command方法内却出现结果陌生的工具类Tool。商家类Business其实并不需要知道工具类Tool的存在,他只与维修师傅类Worker打交道就行,至于师傅用什么工具,他不care的。
所以,我们需要修改一下:

// 维修师傅
public class Worker {
    public void doWork() {
        Tool tool = new Tool();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调");
    }
}
// 商家
public class Business {
    private Worker worker;
    public Business() {
        worker = new Worker();
    }
    public void command() {
        worker.doWork();
    }
}

这样修改之后,商家类Business就不再依赖工具类Tool了,因为根本不需要知道。

但是也不能和朋友类过于“亲密”,知道就好,还是延续上面的例子说明。维修空调可能需要很多工具,除了扳手,还有螺丝刀,清洁工具等。

// 工具接口
public interface Tool {
    String getName();
}
// 扳手工具类
public class BanShou implements Tool {
    return "扳手";
} 
// 螺丝刀工具类
public class LuoSiDao implements Tool {
    return "螺丝刀";
}
// 清洁工具工具类
public class QingJieTool implements Tool {
    return "清洁工具";
}
// 维修师傅
public class Worker {
    // 用扳手修空调
    public boolean doWork1() {
        BanShou tool = new BanShou();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,没修好");
        return false;
    }
    // 用螺丝刀修空调
    public boolean doWork2() {
        LuoSiDao tool = new LuoSiDao();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,没修好");
        return false;
    }
    // 用清洁工具修空调
    public boolean doWork3() {
        QingJieTool tool = new QingJieTool();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,修好了");
        return false;
    }
}
// 商家
public class Business {
    private Worker worker;
    public Business() {
        worker = new Worker();
    }
    public void command() {
        if (worker.doWork1()) {
            System.out.println("维修师傅使用扳手修好了空调");
        } else if (worker.doWork2()) {
            System.out.println("维修师傅使用螺丝刀修好了空调");
        } else if (worker.doWork3()) {
            System.out.println("维修师傅使用清洁工具修好了空调");
        } else {
            System.out.println("维修师傅修不好空调了");
        }
    }
}

例子中,商家类Business的确只与朋友类Worker说话,但是不觉得商家类Business知道管太多了吗?还要“指挥”维修师傅类Worker怎么去修。这是因为维修师傅类Worker“告诉”商家类Business太多“秘密”了,也就是公布太多方法了!既然知道原因,那就把方法私有化,自己知道就行:

// 维修师傅
public class Worker {
    // 用扳手修空调
    private boolean doWork1() {
        BanShou tool = new BanShou();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,没修好");
        return false;
    }
    // 用螺丝刀修空调
    private boolean doWork2() {
        LuoSiDao tool = new LuoSiDao();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,没修好");
        return false;
    }
    // 用清洁工具修空调
    private boolean doWork3() {
        QingJieTool tool = new QingJieTool();
        System.out.println("维修师傅用" + tool.getName() + "在维修空调,修好了");
        return false;
    }
    // 修空调
    public void doWork() {
        if (doWork1()) {
            System.out.println("维修师傅使用扳手修好了空调");
        } else if (doWork2()) {
            System.out.println("维修师傅使用螺丝刀修好了空调");
        } else if (doWork3()) {
            System.out.println("维修师傅使用清洁工具修好了空调");
        } else {
            System.out.println("维修师傅修不好空调了");
        }
    }
}
// 商家
public class Business {
    private Worker worker;
    public Business() {
        worker = new Worker();
    }
    public void command() {
        worker.doWork();
    }
}

维修师傅值提供一个方法,就是维修空调,至于怎么维修,那就是维修师傅自己的事了!这样,即使维修师傅更换维修方式,也和商家无关,商家类Business不用做任何修改!

小结

综上,最少知道原则有2个核心思想:

  1. 尽量不要和陌生类产生依赖关系;
  2. 尽量不要知道朋友类太多细节;

总得来说,迪米特法则的主要目的是减少类没必要的依赖,降低类之间的耦合度

你不知道的SAM V系列MCU:SAM V MCU基于 ARM Cortex:trade_mark:-M7 的微控制器系列可提供最佳的连接接口组合,包括以太网 AVB、MediaLB、USB 和 CAN-FD,以及可提供高达 1500 CoreMark 的高性能 ARM Cortex-M 内核。SAM V MCU专注于音频放大器、汽车通信控制单元或车头单元的车载信息娱乐链接。 关键特性: 高性能—由于 Cortex-M7 能够以 300 MHz 的频率运行,外加前所未有的 DSP 性能,可实现高达 1500 CoreMark 先进的存储器架构— 高达 384 KB 的多端口存储器,其中高达 256 KB 可分配作为紧密耦合存储器(数据和指令),实现以 300 MHz 频率运行时零等待 以太网 AVB— SAM V71 在以太网 MAC 中嵌入了对音频视频桥接 (AVB) 的特定硬件支持。在 MAC 的硬件中实现了基于信用的流量整形,从而无需 CPU 干预 高速 USB— 主机和器件模式高速 USB 控制器集成了 PHY 以降低 BOM 成本 MOST 连接— MediaLB 3 线接口可无缝集成到 MOST 总线 音频接口— 灵活的 TDM/I2S 接口可以连接音频源、编解码器或 DSP CAN-FD— 最新的 CAN 2.0 和 CAN 灵活数据速率 (FD) 控制器可实现更高带宽 汽车等级— 通过 AEC-Q100 等级 2 (-40C/105C) 认证 2015年最新评估开发板——SAM V71 Xplained Atmel年初刚刚推出了基于SAM V71Xplained评估套件,目前已在官网发布出售。 开发板资源: 处理器:ATSAMV71Q21(ATSAMV71Q21数据手册) 用户:一个电源开关按钮、一个机械复位按钮、两个用户按钮、两个黄色LED指示灯 存储:2MB SDRAM、2MB QSPI Flash、256KByte EEPROM 网口:IEEE 802.3az 10Base-T/100Base-TX Ethernet RMII PHY 媒体接口:立体音频编解码器、相机接口、耳机和麦克风接口 SDIO接口SD连接器、CAN收发器 MediaLB接口 接口:外部调试连接器接口、一个扩展LCD接口、两个外部扩展接口、调试接口、虚拟COM口、USB接口 电源:外部电源输入、USB供电 用到的主要芯片: 基于 ARM Cortex:trade_mark:-M7 的微控制器:ATSAMV71Q21 AVR 32-bit RISC MCU:AT32UC3A4256J CAN收发器:ATA6561-GBQW 超低功耗、便携式音频编解码器:WM8904 IEEE 802.3az 10Base-T/100Base-TX Ethernet RMII PHY:KSZ8061RNBVA 2kbit I2C EEPROM:AT24MAC402-MAHM-T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值