第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念.

第2篇, 避免在构建对象时写出不易测试的代码.

本文是第3篇, 讲述依赖项和迪米特法则.

迪米特法则 (Law of Demeter)

还是使用建造汽车的例子. 生产汽车的时候需要轮胎, 组装时需要什么型号的轮胎, 就请求该型号的轮胎, 然后相关人员会从库房把该型号的轮胎送到产线用于组装.

我相信很少有汽车厂会这样做: 生产汽车时, 汽车组装工拿着库房的钥匙, 自己去库房从各种各样的轮胎中找所需要的型号..

这就是违反迪米特法则的一个例子.

迪米特法则大概的意思是: "只访问你自己创建的对象, 或者作为参数传给你的对象. 不要通过其它对象间接的访问对象"

用一句话归纳迪米特法则就是: "只与直系朋友交谈, 不要和陌生人交谈".

注意: 迪米特法则其实并不算严格的法则, 它只是一个非常有益的指导性原则.

存在的问题

用代码形容上面的例子就是:

这违反了迪米特法则, 导致了以下问题:

  • 造成了BenzCar和Warehouse以及MichelinTire之间的紧耦合, 而实际上BenzCar只需要MichelinTire.
  • 测试时, 设置会很麻烦. 代码里Warehouse是直系朋友, MichelinTire是陌生人. 我们需要为Warehouse和MichelinTire同时设置测试替身.
  • 真正需要的依赖项没有明确在构造函数里定义. 这里Warehouse相当于是一个容器, 测试时, 我们可能会不知道要为Warehouse里的哪个东西做测试替身.

危险信号

下列写法可能意味着您的代码违反了迪米特法则:

  • 代码里有这样的调用: "warehouse.getTire.getMichelinTire", 有一连串的点".". 但是有时候这样做是可以的, 例如流畅(fluent)形式的建造者模式就可以, 因为fluent接口通常会返回对象本身, 然后再去使用该对象.
  • 依赖于容器. 例如把 IocContainer作为依赖注入使用.
  • 依赖项的名称为XxxContext, XxxContainer, XxxEnvironment, XxxManager, XxxServiceLocator.
  • 测试时需要创建返回mocks的mock对象.
  • 测试时的设置非常麻烦.

解决办法

解决办法就是遵从迪米特法则.

只注入我们直接需要的依赖项, 直接使用它们. 这样就会保证依赖项很明确, 测试的时候一眼就能看出依赖于哪些对象.

代码示例

例子一

下面这个违反了迪米特法则, 直接注入的是Warehouse, 而实际用到的却是MichelinTire:

正确的做法是, 注入直接使用的依赖项:

例子二

下面的代码也违反了迪米特法则, 它注入了一个容器类的对象:

这个ServiceLocator就相当于是一个容器. 这样用的话, 写测试的人可能根本无法知道需要使用容器里面的哪个对象.

你也许会说这样做灵活(我以前也经常这样做), 但是重构的时候, 这里很容易出错, 因为根本看不出来真正依赖的是哪个对象.

正确的做法还是应该注入直接需要的依赖项:

Law of Demeter相关的内容就简单介绍这些.

最新文章

  1. 深入理解DOM节点关系
  2. WebService学习总结(四)——调用第三方提供的webService服务
  3. (java oracle)以bean和array为参数的存储过程及dao部分代码
  4. MySQL 调优基础(二) Linux内存管理
  5. ServiceStack.Text 更快的序列化
  6. 十大谷歌Google搜索技巧分享
  7. windows查看端口占用
  8. 比较合并工具vimdiff的主要用法归纳
  9. JMS - 消息选择器
  10. 再回首,Java温故知新(十一):Java反射
  11. C# 中的委托和事件[转自张子扬]
  12. Python3 正则表达式特殊符号及用法(详细列表) http://bbs.fishc.com/thread-57691-1-1.html (出处: 鱼C论坛)
  13. Cordova WP8 插件开发
  14. 客户端登录验证 -- ESFramework 4.0 快速上手(15)
  15. IntelliJ IDEA 2016.1.4 git 切换分支详解
  16. pod install 出现 Unable to find a specification for `xxxxx` 解决方案
  17. mysql中csv文件的导入导出
  18. Linux内存管理 (11)page引用计数
  19. 【batch】命令对比两个文件夹下的文件(增删改的对比)
  20. Conclusions about Deep Learning with Python

热门文章

  1. 强大css3制作新浪LOGO 胜过PS
  2. 架构实例之Demo_JSP_JavaBean_Servlet
  3. 几个国内速度最快的centos yum(更新源)
  4. java中的自增问题
  5. Zabbix 监控 Nginx 状态
  6. ADO.NET笔记——带参数的查询防止SQL注入攻击
  7. android studio 报ambiguous method call
  8. php获取post参数的几种方式
  9. Android View动画
  10. 在MVC里使用 HttpContext.Response输出内容
  11. Python基础篇-day6
  12. web.xml中常用元素的解读
  13. Go 程序的性能优化及 pprof 的使用
  14. 痞子衡嵌入式:串口调试工具Jays-PyCOM诞生记(5)- 软件优化
  15. CentOS设置服务开机启动的两种方法
  16. 深入了解UML类图
  17. HDU 1114
  18. jquery首页图片轮播
  19. 【DB2】Event monitor for locking
  20. 用Python来玩微信跳一跳