Java设计模式(3:接口隔离原则和迪米特法则详解)
一、接口隔离原则
使用多个接口,而不使用单一的接口,客户端不应该依赖它不需要的接口。尽量的细化接口的职责,降低类的耦合度。
我们先来看一个例子:
小明家附近新开了一家动物园,里面有老虎、鸟儿、长颈鹿.....周末在逛动物园的时候,小明突发奇想,想用一种方式记录一下这些动物的习性,于是他将老虎和鸟儿的习性结合了一下,写了下面这段代码:
动物行为
// 动物行为
public interface Animal {
// 吃
public void eat();
// 游泳
public void swim();
// 飞
public void fly();
}
老虎Tiger
// 老虎
public class Tiger implements Animal {
@Override
public void eat() {
System.out.println("老虎在吃鸡肉.....");
}
@Override
public void swim() {
System.out.println("老虎在游泳.....");
}
@Override
public void fly() {
System.out.println("老虎不能飞.....");
}
}
小鸟Brid
// 小鸟
public class Brid implements Animal {
@Override
public void eat() {
System.out.println("小鸟在吃虫子.....");
}
@Override
public void swim() {
System.out.println("小鸟不会游泳.....");
}
@Override
public void fly() {
System.out.println("小鸟正在飞.....");
}
}
写完上面的三段代码后,小明发现了问题:在
Animal
接口的三个方法中,Tiger
是不会飞的,所以fly()
方法对于Tiger
是没有用的;Bird
是不会游泳的,所以swim()
方法对于Bird
是没有用的。这样一来,Brid
类和Tiger
类都会空置一个方法,对于代码的结构设计来说不太合理。于是,他划掉了上面的三段代码,仔细思索了一会儿,写出了下面这几段代码:
// 游泳
public interface ISwim {
public void swim();
}
// 吃
public interface IEat {
public void eat();
}
// 飞
public interface IFly {
public void fly();
}
小鸟Bird
// 小鸟
public class Brid implements IEat,IFly {
@Override
public void eat() {
System.out.println("小鸟在吃虫子.....");
}
@Override
public void fly() {
System.out.println("小鸟正在飞.....");
}
}
老虎Tiger
// 老虎
public class Tiger implements IEat,ISwim {
@Override
public void eat() {
System.out.println("老虎在吃鸡肉.....");
}
@Override
public void swim() {
System.out.println("老虎在游泳.....");
}
}
这样来看,将
eat
、swim
、fly
三种方法拆分开来,分别放在三个不同的接口里,这样动物拥有哪几种习性就实现哪几个接口,不会再用空置的方法存在,这样看起来也简洁明了,来看看类图:
二、迪米特法则
又被成为最少知道原则,指的是一个对象应该对其他对象保持最少的了解。一个实体类应当尽量少地和其他实体之间发生相互作用,使得系统模块相互独立。形象来说就是:只和朋友交流,不和陌生人说话。
迪米特法则认为,一个对象或方法,它只能够调用以下对象:
- 该对象本身
- 作为参数传进来的对象
- 在方法内创建的对象
我们先来模拟一个超市购物的场景:顾客Customer
到收银台结账,收银员PaperBoy
负责收钱。
顾客的钱包Wallet
// 钱包
public class Wallet {
// 钱包里装的钱
private Float value;
// 构造器
public Wallet(Float value) {
this.value = value;
}
// 获得钱包里的钱的金额
public Float getMoney(){
return this.value;
}
// 付账时 减钱
public void reduceMoney(Float money){
this.value -= money;
}
}
顾客Customer
// 顾客
public class Customer {
private Wallet wallet = new Wallet(50f);
public Wallet getWallet() {
return wallet;
}
}
收银员PaperBoy
// 收银员
public class PaperBoy {
// 收银员收钱
public void charge(Customer customer,Float money){
Wallet wallet = customer.getWallet();
if (wallet.getMoney() >= money){
System.out.println("顾客付账:" + money +"元");
// 减去 应付的钱
wallet.reduceMoney(money);
System.out.println("钱包里还剩:"+wallet.getMoney()+"元");
} else {
System.out.println("钱包里的金额不够......");
}
}
}
测试、运行
// 测试
public static void main(String[] args) {
PaperBoy paperBoy = new PaperBoy();
Customer customer = new Customer();
paperBoy.charge(customer,20f);
}
从测试代码和运行的结果来看,好像并没有什么问题。让我们来看一下类图:
从类图中我们发现:PaperBoy
类与Wallet
类有着千丝万缕的关系,顾客(Customer
)的钱包(Wallet
)好像并不是自己来控制的,而是由收银员(PaperBoy
)来决定的,就连钱包(Wallet
)里面的钱够不够也是由收银员(PaperBoy
)来判断的;相当于顾客(Customer
)将自己的钱包(Wallet
)暴露给了收银(PaperBoy
),这样来看,问题就很严重了,顾客(Customer
)的隐私受到了侵犯,说大点就是民事纠纷,是可以上法庭的,可以通过法律追究责任的。所以我们思考良久,将上述代码改成下面这般:
钱包Wallet
类不变,顾客Customer
去掉给出钱包的getWallet()
方法,增加付钱的pay()
方法:
// 顾客
public class Customer {
private Wallet wallet = new Wallet(50f);
// 顾客自己付钱
public void pay(Float money){
if (wallet.getMoney() >= money){
System.out.println("顾客付账:" + money +"元");
// 减去 应付的钱
wallet.reduceMoney(money);
System.out.println("钱包里还剩:"+wallet.getMoney()+"元");
} else {
System.out.println("钱包里的金额不够......");
}
}
}
收银员PaperBoy
类中的charge()
方法中的代码删除原有的逻辑,改为调用顾客Customer
类中的付钱pay()
方法:
// 收银员
public class PaperBoy {
// 收银员收钱
public void charge(Customer customer,Float money){
customer.pay(money);
}
}
测试代码不变,我们再来看看类图:
从类的结构图来看:收银员PaperBoy
只和顾客Customer
有联系,钱包Wallet
只和顾客Customer
有联系。再此情况下,如果把钱包Wallet
也当作一个人来看的话,这个就是如下的关系:
- 顾客
Customer
和钱包Wallet
是朋友 - 顾客
Customer
和收银员PaperBoy
是朋友 - 钱包
Wallet
和收银员PaperBoy
是陌生人
这个就符合我们所说的迪米特法则中的核心:只和朋友交流,不和陌生人说话。
Java设计模式(3:接口隔离原则和迪米特法则详解)的更多相关文章
- 设计模式之接口隔离原则(ISP)
一.定义: ISP:Interface Segregation Principle 接口隔离原则表明客户端不应该被强迫实现一些他们不会使用的接口,应该把胖接口中的方法分组,然后用多个接口代替它,每个接 ...
- IOS设计模式的六大设计原则之迪米特法则(LOD,Law Of Demeter)
定义 狭义的迪米特法则定义:也叫最少知识原则(LKP,Least Knowledge Principle).如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用.如果其中的一个类需要调用 ...
- 想真正了解JAVA设计模式看着一篇就够了。 详解+代码实例
Java 设计模式 设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结 设计模式分为 23 种经典的模式,根据用途我们又可以分为三大类.分别是创建型模式.结构型模式和行为型模式 列举几种设 ...
- 设计模式 第一天 UML图,设计模式原则:开闭原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则,简单工厂模式
1 课程大纲 2 UML的概述 总结: UML unified model language 统一建模语言 一共有十种图: 类图 用例图 时序图 * 对象图 包图 组件图 部署图 协作图 状态图 (最 ...
- java设计模式学习笔记--接口隔离原则
接口隔离原则简述 客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应建立在最小的接口上 应用场景 如下UML图 类A通过接口Interface1依赖类B,类C通过接口Interface1依赖类 ...
- [设计模式]<<设计模式之禅>>关于接口隔离原则
在讲接口隔离原则之前,先明确一下我们的主角——接口.接口分为两种: ● 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实例,它是对一个类型的事物的描述 ...
- ZT 设计模式六大原则(4):接口隔离原则
设计模式六大原则(4):接口隔离原则 分类: 设计模式 2012-02-27 08:32 17948人阅读 评论(21) 收藏 举报 设计模式classinterfacecstring框架 定义:客户 ...
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛.博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文.博主的想法是,既然要完善知识体系 ...
- 设计模式之六大原则——接口隔离原则(ISP)
设计模式之六大原则——接口隔离原则(ISP) 转载于:http://www.cnblogs.com/muzongyan/archive/2010/08/04/1792528.html 接口隔离原则 ...
随机推荐
- Portswigger web security academy:HTTP request smuggling
HTTP request smuggling 目录 HTTP request smuggling HTTP request smuggling, basic CL.TE vulnerability H ...
- 简单写个logictic回归
最近做华为软件精英挑战赛热身赛,给出的demo是使用logistic做的金融风控,比赛要求很严格,如果使用Python 进行训练那么不能使用任何第三方机器学习库,只能使用Python和原生numpy1 ...
- 《前端运维》一、Linux基础--基础命令(1)
在开始之前,你需要做一些准备工作,去阿里买一台服务器,服务器的具体细节其实并不是十分重要,我也不会在这里一步一步的教大家如何去买一个服务器.百度一下足够了,但是还是要贴一下这篇文章中,我所使用的服务器 ...
- Day003 彻底搞懂++、--
彻底搞懂++.-- ++.--都是一目运算符 b=a++(把a的值先赋给b,a再自增1) b=++a(a先自增1,再赋给b) 通过一个例子理解 int a=1; int b=a++; int c=++ ...
- 大学四年因为分享了这些软件测试常用软件,我成了别人眼中的(lei)大神(feng)!
依稀记得,毕业那天,我们辅导员发给我毕业证的时候对我说"你可是咱们系的风云人物啊",哎呀,别提当时多开心啦????,嗯,我们辅导员是所有辅导员中最漂亮的一个,真的???? 不过,辅 ...
- python爬虫——《英雄联盟》英雄及皮肤图片
还记得那些年一起网吧开黑通宵的日子吗?<英雄联盟>绝对是大学时期的风靡游戏,即使毕业多年的大学同学相聚,难免不怀念一番当时一起玩<英雄联盟>的日子. 今天就给大家分享一下英雄及 ...
- Docker镜像讲解
Docker镜像讲解 镜像是什么 镜像是一种轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境的开发软件,它包含运行某个软件做需要的所有的内容,包括代码,运行时,库,环境变量和配置文件. ...
- Unix下 压缩和解压缩命令
范例: .tar 解包:tar -xvf FileName.tar 打包:tar -cvf FileName.tar DirName (注:tar是打包,不是压缩!) ---------------- ...
- 解决 Ubuntu 无法使用 root 用户进行 ssh 远程登陆
解决 Ubuntu 无法使用 root 用户进行 ssh 远程登陆 操作系统 Ubuntu 20.04.2 LTS 一.修改sshd配置文件 //打开 /etc/ssh/sshd_config 配置文 ...
- 运维常用shell脚本一(系统指标巡检、自动创建用户、跳板机)
一.系统指标巡检脚本 #!/bin/bash menu(){ cat <<EOF +---------------------------------------------+ | 日常巡 ...