浅谈设计模式-迪米特法则
书接上回,本篇继续讲一下设计模式六大原则(有些书认为是7大原则)
原则定义
迪米特法则(Law of Demeter,LoD)的定义有点意思,有2种表述
1> 最少知道原则,指一个对象应当对其他对象有尽可能少的了解。
2> 只和直接的朋友交流(也有说法:不要与陌生人说话)
初看有点令人摸不着头脑,细细品品,好像是那么一回事,说下个人理解:
1> 最少知道原则,指一个对象应当对其他对象有尽可能少的了解。
其实可以理解为,在符合设计(开发)规范前提下,对象与对象间能不交互就不要交互,保持对象的独立性,降低类间耦合度,提高模块的复用性。
2>只和直接的朋友交流(也有说法:不要与陌生人说话)
这里的朋友,是朋友类的意思,理解起来有点抽象,因为我们对象朋友类这词有点陌生。迪米特法则提出者给出朋友类定义:A类如果被B类依赖,那A类就是B类的朋友类。下面都是B类的朋友类存在形式
public class A{//....
}
成员变量:
public class B{private A a;
}
方法参数:
public class B{public void someMethod(A a){...}
}
方法返回值:
public class B{public A someMethod(){return a;}
}
需要注意,这种形式存在时,A类不算是B类的朋友类,而是陌生人
方法中,A类左右局部变量/对象
public class B{public void someMethod(){A a = new A();}
}
理想状态就是这样啦,但真实操作哪有那么理想,类多之后肯定存在或多或少类间直接较互,特别是上面讲的与陌生类交互,该怎么办?迪米特法则建议通过友元类的方式类避免。这里的友元类可以理解为:中介类,也可以理解为一种统一调配的类。下面例子:
public class C{void doWork(){...}
}//A不方便直接与C交互
public class A{public void doWork(){C c = new C();c.doWork();}
}//可以借助B
public class B{public void doWork(){this.getC().doWork();}public C getC(){return new C();}
}//改造后的A
public class A{public void doWork(B b){b.doWork();}
}
B为友元类,A借助B类实现与C类的间接交互。
案例分析
需求:乘客预约出租车去上班
//出租车
public class TaxiCar {public void run() {System.out.println("司机大叔开始达到目的地....");}
}
//司机
public class Driver {public TaxiCar getCar() {System.out.println("司机大叔按约定时间达到约定地点等待客户...");return new TaxiCar();}
}
//乘客
public class Passenger {public void goToWork(Driver driver) {TaxiCar car = driver.getCar();car.run();}
}
测试:
//测试
public class App {public static void main(String[] args) {//客人Passenger p = new Passenger();//司机Driver driver = new Driver();//上班p.goToWork(driver);}
}
结果:
司机大叔按约定时间达到约定地点等待客户...
司机大叔开始达到目的地....
解析
上面模拟乘客上班场景,乘客预约司机,司机使用出租车送乘客上班。咋一看毛事没有啥问题,细看有点怪怪的,比如Passenger类goToWork方法,传入Driver类之后,通过Driver类的getCar方法,然后在使用TaxiCar类的run方法完成goToWork功能。这里的TaxiCar对于Passenger类是陌生类,违背了迪米特法则不与陌生人交流的要求。
改进版
修改后Drvier类
//司机
public class Driver {//私有private TaxiCar getCar() {System.out.println("司机大叔按约定时间达到约定地点等待客户...");return new TaxiCar();}//新增驾车方法public void drive(){TaxiCar car = getCar();car.run();}
}
修改后Passenger类
//乘客
public class Passenger {public void goToWork(Driver driver) {driver.drive();}
}
解析:
改进后的案例就合理多了。Passenger类不需要在意TaxiCar类怎么操作,只需要Driver能完成driver功能即可。Driver使用drive方法遮蔽Passenger类对TaxiCar类直接引用,这符合迪米特法则。
使用注意
迪米特法则,对类之间交互的宽度与深度进行限制,正确使用可以提高系统架构复用率跟拓展性。但过度使用迪米特方法,会使用系统产生大量的友元类,从而增加系统的复杂性,使模块之间的通信效率降低。所以,在釆用迪米特法则时要反复权衡,在确保高内聚和低耦合同时,保证系统的结构清晰。
那实际编码时,需要注意什么呢?一下几点:
1:设计类时,考虑类间的耦合情况,合理减少类间交互,如果必要可以尝试使用内部类
2:尽可能使用private访问权限修饰属性成员,不外泄内部信息
3:满足需求设计前提,可以将类设置成final类
4:使用JavaBean规范,合理暴露属性成员
运用
这次使用shrio身份验证为例子展开讲:
Shiro进行身份验证涉及到几个参与方:
Subject : 用户对象抽象类,里面封装用户信息与用户相关动作,比如鉴权与授权委托操作
UsernameAndPasswordToken:用户身份信息(username, password)封装对象
SecurityManager :shiro的大管家,负责资源调配
Realms:数据来源中间对象,负责与数据库,或者其他来源数据对接,转换成shiro可操作对象
Authentication:身份验证器
整个身份验证流程
UsernameAndPasswordToken
UsernameAndPasswordToken token = new UsernameAndPasswordToken("账号", "密码");
Subject类
public void login(AuthenticationToken token) throws AuthenticationException {Subject subject = securityManager.login(this, token);
}
SecurityManager 类
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {authenticate(token);
}public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {return this.authenticator.authenticate(token);
}
Authentication类
public final AuthenticationInfo authenticate(AuthenticationToken token){doAuthenticate(token);
}protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) {assertRealmsConfigured();Collection<Realm> realms = getRealms();if (realms.size() == 1) {return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);} else {return doMultiRealmAuthentication(realms, authenticationToken);}
}
结合上面核心代码,看下,一层一层委托下去,subject的login操作只需要委托给SecurityManager 类操作即可,不需要关注背后如何实现,只跟它朋友类SecurityManager 交互,这就是典型的迪米特法则使用。有兴趣大家跟踪下shiro鉴权操作,大同小异。
总结
迪米特法则使用过程中要明确的:
1:最少知道原则: A类减少与其他类的交互,其他类仅暴露A类需要方法或属性
2:不与陌生类交互:A类不可避免与陌生类交互,需要合理使用友元类(中介类)
浅谈设计模式-迪米特法则相关推荐
- 设计模式 迪米特法则
设计模式 迪米特法则 只和朋友交流 Only talk to your immediate friends 只与直接的朋友通信.即每个对象都有耦合关系,对象之间有耦合. 定义老师类 public cl ...
- 浅谈设计模式 | 先有鸡还是先有蛋?先有代码后有设计模式还是先有设计模式再写代码?
前言 一.面向对象的三大特性 1. 封装 2.继承 3.多态 二.面向对象七个设计原则 1.单一职责原则 2.开放封闭原则 3.里氏替换原则 4.接口隔离原则 5.依赖倒置原则 6.合成复用原则 7. ...
- 【大话设计模式】——浅谈设计模式基础
初学设计模式给我最大的感受是:人类真是伟大啊!单单是设计模式的基础课程就让我感受到了强烈的生活气息. 个人感觉<大话设计模式>这本书写的真好.让貌似非常晦涩难懂的设计模式变的生活化.趣味化 ...
- 浅谈设计模式及python实现
设计模式及Python实现 设计模式是什么? Christopher Alexander:"每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心.这样你就能一次又一次 ...
- 迪米特法则 java_java设计模式--迪米特法则
基本介绍 1.一个对象应该对其他对象保持最少的了解 2.类与类关系越密切,耦合度越大 3.迪米特法则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好.也就是说,对于被依赖的类不管多么复杂,都尽量 ...
- [设计模式]迪米特法则
迪米特法则 又叫最少知识法则 类中的成员属性和成员方法,如果不需要对外暴露,就不要设成public. 代码如下: #include <iostream> #include <stri ...
- Java设计模式-迪米特法则
迪米特法则 [Low Of Demeter] 定义:一个对象应该对其他对象保持最少的了解. 问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大. 解决 ...
- 23种设计模式-迪米特法则
概念: 1) 一个对象应该对其他对象保持最少的了解 2) 类与类关系越密切,耦合度越大 3) 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的 越少越好. ...
- 浅谈设计模式在iOS开发实战项目中的应用
在我们日常的开发中设计模式伴随着项目的各个模块,巧妙地使用设计模式可以让我们写出更高效,简洁,优美的代码.可是因为对于设计模式的不熟悉,很多高效的设计模式并没有被很好地使用起来,而最近也正好在revi ...
最新文章
- apache用户认证
- 设计模式总结(Java)—— 观察者模式
- linux防火墙添加端口并开闭防火墙
- MongoDB文档对象字段属性合并的2种转换方法
- 老鼠实验中老鼠的数量变化曲线
- python删除文件和linux删除文件区别_使用Python批量删除文件列表
- java for 线程_如何在for循环中使用多线程
- sql中全文检索的具体细节
- 3Dmax读取丢失的贴图的方法
- 小米笔记本 镜像_小米笔记本Air 13.3原装出厂WIN10 2004 ISO镜像下载
- Kaggle共享单车需求项目详解
- java电子通讯录毕业设计_JAVA电子通讯录(带系统托盘)009
- Bouncing Ball
- matlab中的灰色预测,灰色预测MATLAB程序
- SQLiteSpy下载安装
- 《提问的智慧》 - 懒人的脑图
- AHU-727 美妙音乐 【DP】
- QQ是怎么处理消息的
- 华为平板M3能用鸿蒙吗,华为平板M3怎么样 麒麟950处理器搭配快充只要1888!
- C语言程序设计第五章循环结构程序设计总结
热门文章
- 存贮论(一):基本概念、无约束的确定型存贮模型
- 有关java中equals()与hashCode()的探讨
- Python 生成圣诞树 Santa Tree Generator 不务正业系列#1
- 基于MSP430单片机风光互补控制路灯设计(毕业设计资料)
- java.lang.IllegalArgumentException: object is not an instance of declaring class
- Qtdesinger 去除 Text Browser边框
- validate表单验证的用法
- 小程序,快应用,心是够大,但胸不大
- 计算机软件3dmax在展览中的研究,博物馆3D扫描技术的应用及前景
- 手机腾讯云计算机广告怎么关,教你关闭烦人的电脑弹窗广告