报童、钱包和迪米特法则(设计模式迪米特原则经典论文翻译)
写在文章前:
或许你写过无数代码,参与过很多大型系统的设计,但,你是否曾经思考过,你的设计可扩展、易维护么,在高速变化的互联网世界里,它能经得起这种急速变化的考验么?如果你没想过这些问题,那请先放下你那些牛逼的梦想,放下你的高傲,好好去理解、回味设计六大原则和23种设计模式,因为它们是你腾飞的基石。今天,我勇敢的尝试翻译一篇有关设计原则的经典论文,希望对大家有帮助。(翻译是一项很费时、费精力的活,而且博主英语水平也不是特别好,翻译时多采用意译,见谅)
前言
在我读大学的时候,我的一个教授说每个程序员都有一个“装满各种小技巧的包”,这些小技巧,也就是解决问题的方法,在我们的个人经历中,会一遍又一遍的用到。他说,他的工作就是“把更多的小技巧装入我们的包里”。他所说的“小技巧”也就是如设计模式和设计风格(原文为idioms)。
这篇论文要讨论的是一个我特别喜欢的“小技巧”。相对于被划为设计模式(经管常被划分为设计模式),把它划为设计风格可能更合适。在理解了这个设计风格并知道怎么使用它,我相信你的代码会更优雅、更不容易出错,且更易维护。我马上要讲述一个如何减少你代码中对象耦合的方法。这个方法有一个很棒的名字:迪米特法则
现在我们假设有一个送报的小孩,他从他的顾客那里得到送报的钱。让我们为顾客定义一个类,几行代码表示送报小孩从顾客收钱,和一个送报小孩会执行的一个代码片段。
编写我们的代码
好,让我们开始写顾客这个类。顾客类可能有个姓和名,可能有一个银行账户,或者购物地址等。为了例子的简单考虑,我们定义了一个简单的顾客类。
考虑到倒霉的长度,我们省略了setters。从这个例子看,很显然我们还需要定义一个钱包类:
好了,这是一个简单的钱包。以后可能给它添加各种数据结构,但这个例子,这个钱包足够了。
现在利用这些,我们可以开始做一些有用的事了。让我们的送报小孩按响门铃,然后向顾客要求送报的报酬。如果我们把这写成代码,代码如下:
这段代码表示送报小孩从顾客那拿到钱包,检查钱包以确保钱够,然后把钱从顾客钱包取出,放到自己钱包。
为什么这样很糟糕
那么,这段代码糟糕在哪?好,让我们把这段代码用真实的生活场景还原。
很显然,当送报小孩索要报酬时,顾客直接让小孩从自己的口袋取出钱包,并从钱包里拿走报酬。
我不知道你会不会这样,反正我是很少让人拿走我的钱包。在现实中,上面的场景会遇到很多困难,更不用说相信那小孩很诚实,只拿走自己应得的报酬。如果以后钱包有信用卡啥的,他还能拿走信用卡。但是,这个问题的本质是,“小孩知道了更多他不需要知道的信息”
那是一个很重要的概念。“送报小孩”这个类现在知道顾客有个钱包,而且还能操作它。当我们编译小孩这个类,我们还需要顾客和钱包这两个类。这三个类紧紧的耦合在了一起。如果我们改变钱包类,我们可能还需要修改其他两个类。
还有一个经典的难题可能会遇到。如果顾客的钱包被偷了,那会发生什么?在我们这个例子中,或许昨晚有个贼就偷了这个钱包,然后有人把代码修改了,把钱包置为null,如下:
victim.setWallet(null);
这看起来像是一个很合理的假设。但是对于我们的送报小孩类呢?回头看看代码。我们假设钱包是存在的!我们的代码执行时将抛出空指针异常。
我们可以在任何方法调用钱包类之前,检查它是否为空,但这会使我们的代码更乱。而真实场景会更坏--“如果我的顾客有钱包,就看看钱包里有多少钱……如果他能付钱,拿走钱”。很显然,我们被弄晕了。
修改原始代码
解决这个问题的更合适的方式是采用符合现实场景的方法:“当小孩来到门前要求报酬时,顾客不会把钱包交给小孩,而小孩甚至都不需要知道顾客有个钱包”。
注意,顾客不再有"getWallet()"方法了,但是他有一个getPayMent方法。让我们看看小孩的:
为什么现在更好
首先,现在的模型更好的符合现实世界的情况。小孩现在是向顾客索要报酬,而没有机会拿到钱包。
其次,钱包现在可以改变了,但小孩和这种变化彻底隔离开来了。如果钱包的被偷了,顾客会换个钱包,但只要顾客提供的接口保持不变,顾客的客户端不会关心顾客是否换了一个新钱包。代码变得更易维护了。
第三,可能也是最面向对象的理由,我们可以随意改变'getPayment()'的实现了。在第一个例子,我们假设顾客有一个钱包,这导致了我们讨论的空指针异常。在现实世界里,当小孩来到门前,我们的顾客可能从抽屉里取出钱,或者从室友那借。但所有这些业务逻辑,小孩都不需要关心了。所有这些都在'getPayment()'中实现,并且在将来可以改变而不影响小孩的代码。
你也可以听起来更智慧
在开头我提到过这关概念有个名字,叫做“迪米特法则”
一个方法的对象应该只引用该方法中的四种对象(注:可以简单称为"只与直接朋友通信"):
1、它自己
2、它的方法参数
3、它创造或者实例化的任何对象
4、有直接关联的对象
什么时候、怎么使用迪米特法则
1、get的链
最常用到的地方就是,如下
value = object.getX().getY().getTheValue();
(注:通过不停的get获得不同的对象,这样就与很多非直接朋友通信了,所以可以简单记为“减少点”,不过并不是“点多就是违反法则”。不过有篇文章介绍了,请参考The Law of Demeter Is Not A Dot Counting Exercise
)
2、很多临时对象
结论
我希望这篇论文能带给你一些新的东西。或许这些几乎就像常识一样普通。如果真的是这样,那很好。但是,理解它,给它一个统一的命名,然后人们可以使用它相互交流也是很好的。
原文请参考
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
转载于:https://www.cnblogs.com/junyuhuang/p/5630539.html
报童、钱包和迪米特法则(设计模式迪米特原则经典论文翻译)相关推荐
- 迪米特法则(设计模式5)
迪米特法则: 迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说 ...
- 2016-12-28 迪米特法则+依赖倒转原则+里氏替换原则
依赖倒转原则 依赖倒转原则,也翻译成依赖倒置原则,抽象不应该依赖细节,细节应该依赖于抽象,要针对接口编程,而不是对实现编程.如电脑中无论主板.CPU.内存.硬盘都是针对接口设计的,PC电脑硬件的发展, ...
- 面向对象软件设计原则【JAVA】(开闭原则、里氏代换、依赖倒转、接口隔离、迪米特法则、合成复用原则)
软件设计原则[JAVA](开闭原则.里氏代换.依赖倒转.接口隔离.迪米特法则.合成复用原则) 1.开闭原则 2.里氏代换原则 3.依赖倒转原则 4.接口隔离原则 5.迪米特法则 6.合成复用原则 1. ...
- 迪米特法则(最少知道原则)
10.3.5 迪米特法则(最少知道原则)(Demeter Principle) 迪米特法则(Law of Demeter)又叫最少知道原则(Least Knowledge Principle),19 ...
- 开闭原则、迪米特法则、合成复用原则
开闭原则 1,一个软件实体如类,模块和函数应该对外扩展开放,对修改关闭,用抽象构建框架,用实现扩展细节 2.当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化 ...
- 迪米特法则 php,迪米特法则(The Law of Demeter) -解道Jdon
迪米特法则 父母都会教育孩子们,不要和陌生人讲话,如果有陌生人试图和他们讲话,必须告诉爸爸妈妈,这是因为孩子们还不成熟,会相信一切成人告诉他们的事情,我们这样做是为了包含他们. 在面向对象编程中,我们 ...
- 【实验】软件设计原则,迪米特法则与开闭原则
(一)实验原理 1.迪米特法则:不要和"陌生人"说话.或只与你的直接朋友通信. 我们称出现成员变量.方法参数.方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友. ...
- 迪米特法则(最少知识原则)
定义 如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用.如果一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个应用. 迪米特法则强调:在类的结构设计上,每一个类都应该尽量 ...
- 迪米特法则原理(最少知道原则)
定义:是指一个对象类对于其他对象类来说,知道的越少越好.也就是说两个类之间不要有过多的耦合关系,保持最少关联性. 经典语录:只和朋友通信,不合陌生人说话. 也就是说有内在关联的类要内聚,没有直接关系的 ...
最新文章
- [js]uploadify结合jqueryUI弹出框上传,js中的冒出的bug,又被ie坑了
- TOML-to-Go : 帮你快速生成 Go 结构体
- iphone开发证书 纠结许久
- SDN/NFV运营商商业化部署
- 云鲸扫拖一体机器人说明书_云鲸扫拖一体机器人开箱测评。拖地机器人的天花板是什么样的?...
- NFS服务的配置过程
- 学习逆向知识之用于游戏外挂的实现.第二讲,快速寻找植物大战僵尸阳光基址.以及动态基址跟静态基址的区别...
- 【华为】对标谷歌Dropout专利,华为开源自研算法Disout,多项任务表现更佳
- netty冲突 play sbt_播放Cassandra Netty Server空指针异常-问答-阿里云开发者社区-阿里云...
- java面试题笔试常见选择题大全含答案
- 用豆瓣 API 爬《计算机科学丛书》示例
- LabVIEW编程LabVIEW开发 常用运动控制器比较
- 医院子母钟系统-YZ-9200
- 常见低压电器原理及电气符号(接触器、继电器、熔断器、断路器)基本原理及电气间隙与爬电距离
- K8S 三种探针 readinessProbe、livenessProbe和startupProbe
- Coursera 申请助学金流程和材料
- 智能客服 | 5款绝佳客户服务聊天机器人推荐
- [Usaco2010 Dec]Treasure Chest 藏宝箱
- JAVA之旅(三十五)——完结篇,终于把JAVA写完了,真感概呐!
- Oracle数据库条件筛选函数decode,NVL