北风设计模式课程---最少知识原则(Least Knowledge Principle)
北风设计模式课程---最少知识原则(Least Knowledge Principle)
一、总结
一句话总结:
最少知识原则(Least Knowledge Principle),或者称迪米特法则(Law of Demeter):只和自己直接的 "朋友" 交谈。
1、最少知识原则 的好处是什么?
更好的信息隐藏:It leads to better information hiding.
更少的信息重载:It leads to less information overload.
2、最少知识原则 的 “ 只和自己直接的 '朋友' 交谈 ” 具体指(注意)什么?
方法返回的对象的方法:对象应尽可能地避免调用由另一个方法返回的对象的方法
3、如下代码的缺点是什么?
|||-begin
public Emailer(Server server) {…} // taking a server in the constructor
public void sendSupportEmail(String message, String toAddress) {
EmailSystem emailSystem = server.getEmailSystem();
String fromAddress = emailSystem.getFromAddress();
emailSystem.getSenderSubsystem().send(fromAddress, toAddress, message);
}
|||-end
1、复杂而且看起来不必要:Emailer 与多个它可能不是真的需要的 API 进行交互,例如 EmailSystem。
2、依赖太多:依赖于 Server 和 EmailSystem 的内部结构,如果两者之一进行了修改,则 Emailer 有可能被破坏。
3、不能重用:任何其他的 Server 实现也必须包含一个能返回 EmailSystem 的 API。
4、应用最少知识原则优点和缺点?
优点:降低耦合:遵守 Law of Demeter 将降低模块间的耦合,提升了软件的可维护性和可重用性。
缺点:提升复杂度:应用 Law of Demeter 可能会导致不得不在类中设计出很多用于中转的包装方法(Wrapper Method),这会提升类设计的复杂度。
二、最少知识原则(Least Knowledge Principle)
转自或参考:最少知识原则(Least Knowledge Principle)
https://www.cnblogs.com/gaochundong/p/least_knowledge_principle.html">最少知识原则(Least Knowledge Principle)
最少知识原则(Least Knowledge Principle),或者称迪米特法则(Law of Demeter),是一种面向对象程序设计的指导原则,它描述了一种保持代码松耦合的策略。其可简单的归纳为:
Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
每个单元对其他单元只拥有有限的知识,只了解与当前单元紧密联系的单元;
再简洁些:
Each unit should only talk to its friends; don't talk to strangers.
每个单元只能和它的 "朋友" 交谈,不能和 "陌生人" 交谈;
更简洁些:
Only talk to your immediate friends.
只和自己直接的 "朋友" 交谈。
应用到面向对象的程序设计中时,可描述为 "类应该与其协作类进行交互但无需了解它们的内部结构"。
A class should interact directly with its collaborators and be shielded from understanding their internal structure.
迪米特法则(Law of Demeter)由 Northeastern University 的 Ian Holland 在 1987 年提出,"Law of Demeter" 名称是来自当时正在进行的一项研究 "The Demeter Project"。
Demeter = Greek Goddess of Agriculture; grow software in small steps.
在 2004 年,Karl Lieberherr 在其论文 "Controlling the Complexity of Software Designs" 中将 LoD 的定义由 "Only talk to your friends" 改进为:
Only talk to your friends who share your concerns.
改进后的原则称为 LoDC(Law of Demeter for Concerns),它为软件设计带来了两个主要的益处:
It leads to better information hiding.
It leads to less information overload.
即,更好的信息隐藏和更少的信息重载。LoDC 原则在面向方面的软件开发(AOSD:Aspect-Oriented Software Development)中有着良好的应用。
最少知识原则在面向对象编程中的应用
在 "Law of Demeter" 应用于面向对象编程中时,可以简称为 "LoD-F:Law of Demeter for Functions/Methods"。
对于对象 O 中的一个方法 m ,m 方法仅能访问如下这些类型的对象:
- O 对象自身;
- m 方法的参数对象;
- 任何在 m 方法内创建的对象;
- O 对象直接依赖的对象;
具体点儿就是,对象应尽可能地避免调用由另一个方法返回的对象的方法。
现代面向对象程序设计语言通常使用 "." 作为访问标识,LoD 可以被简化为 "仅使用一个点(use only one dot)"。也就是说,代码 a.b.Method() 违反了 LoD,而 a.Method() 则符合 LoD。打个比方,人可以命令一条狗行走,但是不应该直接指挥狗的腿行走,应该由狗去指挥它的腿行走。
你是否见过类似下面这样儿的代码?
public Emailer(Server server) {…} // taking a server in the constructor
public void sendSupportEmail(String message, String toAddress) {
EmailSystem emailSystem = server.getEmailSystem();
String fromAddress = emailSystem.getFromAddress();
emailSystem.getSenderSubsystem().send(fromAddress, toAddress, message);
}
上面这个设计有几点问题:
- 复杂而且看起来不必要。Emailer 与多个它可能不是真的需要的 API 进行交互,例如 EmailSystem。
- 依赖于 Server 和 EmailSystem 的内部结构,如果两者之一进行了修改,则 Emailer 有可能被破坏。
- 不能重用。任何其他的 Server 实现也必须包含一个能返回 EmailSystem 的 API。
除了上面这几个问题之外,还有一个问题是这段代码是可测试的吗?你可能会说肯定可测啊,因为这个类使用了依赖注入(Dependency Injection),我们可以模拟 Server、EmailSystem 和 Sender 类。但真正的问题是,除了多出了这些模拟代码,任何对 API 的修改都将破坏所有的测试用例,使得设计和测试都变得非常脆弱。
解决上述问题的办法就是应用最少知识原则,仅通过构造函数注入直接依赖的对象。Emailer 无需了解是否 Server 类包含了一个 EmailSystem,也不知道 EmailSystem 包含了一个 Sender。
public Emailer(Sender sender, String fromAddress) {…}
public void sendSupportEmail(String message, String toAddress) {
sender.send(fromAddress, toAddress, message);
}
这个设计较为合理些。现在 Emailer 不再依赖 Server 和 EmailSystem,而是通过构造函数得到了所有的依赖项。同时 Emailer 也变得更容易理解,因为所有与其交互的对象都显式的呈现出来。
Emailer 与 Server 和 EmailSystem 也达到了解耦合的效果。Emailer 不再需要了解 Server 和 EmailSystem 的内部结构,任何对 Server 和 EmailSystem 的修改都不再会影响 Emailer。
而且,Emailer 的变得更易被复用。如果切换到另外一个环境中时,仅需实现一个不同的 Sender 即可。
对于测试而言,现在我们仅需模拟 Sender 依赖即可。
应用最少知识原则优点和缺点
优点:遵守 Law of Demeter 将降低模块间的耦合,提升了软件的可维护性和可重用性。
缺点:应用 Law of Demeter 可能会导致不得不在类中设计出很多用于中转的包装方法(Wrapper Method),这会提升类设计的复杂度。
面向对象设计的原则
参考资料
- Principle of Least Knowledge
- Demeter: Aspect-Oriented Software Development
- Law of Demeter
- Controlling the Complexity of Software Designs
- Introducing Demeter and its Laws
- The Paperboy, The Wallet, and The Law Of Demeter
- Principle of Least Knowledge
- Loose Coupling with Demeter
- An Empirical Validation of the Benefits of Adhering to the Law of Demeter
北风设计模式课程---最少知识原则(Least Knowledge Principle)的更多相关文章
- 北风设计模式课程---接口分离原则(Interface Segregation Principle)
北风设计模式课程---接口分离原则(Interface Segregation Principle) 一.总结 一句话总结: 接口分离原则描述为 "客户类不应被强迫依赖那些它们不需要的接口& ...
- 北风设计模式课程---里氏替换原则(Liskov Substitution Principle)
北风设计模式课程---里氏替换原则(Liskov Substitution Principle) 一.总结 一句话总结: 当衍生类能够完全替代它们的基类时:(Liskov Substitution P ...
- 北风设计模式课程---依赖倒置原则(Dependency Inversion Principle)
北风设计模式课程---依赖倒置原则(Dependency Inversion Principle) 一.总结 一句话总结: 面向对象技术的根基:依赖倒置原则(Dependency Inversion ...
- 北风设计模式课程---单一职责原则(Single Responsibility Principle)
北风设计模式课程---单一职责原则(Single Responsibility Principle) 一.总结 一句话总结: 一个类应该有且只有一个变化的原因:单一职责原则(SRP:Single Re ...
- 北风设计模式课程---开放封闭原则(Open Closed Principle)
北风设计模式课程---开放封闭原则(Open Closed Principle) 一.总结 一句话总结: 抽象是开放封闭原则的关键. 1."所有的成员变量都应该设置为私有(Private)& ...
- 最少知识原则(Least Knowledge Principle)
最少知识原则(Least Knowledge Principle),或者称迪米特法则(Law of Demeter),是一种面向对象程序设计的指导原则,它描述了一种保持代码松耦合的策略.其可简单的归纳 ...
- 设计模式之迪米特原则(LOD)(最少知识原则)
来源:迪米特法则(LoD)最初是用来作为面向对象的系统设计风格的一种法则,是很多著名系统,如火星登陆软件系统.木星的欧罗巴卫星轨道飞船的软件系统的指导设计原则. 迪米特法则(LoD)又可分为两种:狭义 ...
- 设计模式值六大原则——迪米特法则(LoD)也称为最少知识原则(LKP)。
定义: 迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP). 一个对象应该对其他对象有最少的了解.通俗地讲,一个类应该对 ...
- [Python设计模式] 第11章 迪米特法则——最少知识原则
github地址:https://github.com/cheesezh/python_design_patterns 迪米特法则 迪米特法则(LoD),也叫最少知识原则,如果两个类不必彼此直接通信, ...
随机推荐
- MySQL-快速入门(6)连接查询、子查询、正则表达式查询、数据的插入删除更新
1.内连接查询:inner join ... on 只有满足条件的记录才能够出现在结果关系中,即完全相等.自连接查询是一种特殊的内连接查询. 2.外连接查询: 1>左外连接 / 左连接:返回包括 ...
- 什么场景下用redis而不用mysql?
redis我们用作缓存,对查询速度要求比较高的应用场景比较适合.对有复杂逻辑关系的存储不适合. mysql是硬盘存储的,在高性能io要求的项目里不能满足需求,而redis所有数据存在内存里,因此要快得 ...
- [项目实战]训练retinanet(pytorch版)
采用github上star比较高的一个开源实现https://github.com/yhenon/pytorch-retinanet 在anaconda中新建了一个环境,因为一开始并没有新建环境,在原 ...
- leetcode第一题(easy)
第一题:题目内容 Given an array of integers, return indices of the two numbers such that they add up to a sp ...
- element ui 选择期 传对象
<template> <el-select value-key="label" v-model="value" placeholder=&qu ...
- 41. First Missing Positive (JAVA)
Given an unsorted integer array, find the smallest missing positive integer. Example 1: Input: [1,2, ...
- iOS之Run Loop详解
转自标哥的技术博客(www.henishuo.com) 前言 做了一年多的IOS开发,对IOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情.想学好一 ...
- 关于ResultSet中getDate\getTime\getTimestamp的区别的记录
getDate() 返回时间的年月日 getTime() 返回时间的时分秒 getTimestamp () 返回时间的年月日 时分秒
- rest_framework框架的分页
class MyPageNumberPagination(PageNumberPagination): page_size = 1 page_query_param = 'page' page_siz ...
- 02python程序设计基础——字符串
字符串方法 format 1.替换字段名 在最简单的情况下,只需向 format 提供要设置其格式的未命名参数,并在格式字符串中使用未命名字段.此时,将按顺序将字段和参数配对.你还可给参数指定名称,这 ...