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 接口隔离原则 ...
随机推荐
- Andrew Ng机器学习算法入门(一):简介
简介 最近在参加一个利用机器学习来解决安全问题的算法比赛,但是对机器学习的算法一直不了解,所以先了解一下机器学习相关的算法. Andrew Ng就是前段时间从百度离职的吴恩达.关于吴恩达是谁,相信程序 ...
- .NET Core 对象( Transient、Scope、Singleton )生命周期详解 (对象创建以及释放)
首先我们在VS2019中创建一个.NET Core的控制台程序,方便演示: 需要安装两个依赖包 Microsoft.Extensions.DependencyInjection 依赖注入对象的具体实现 ...
- 老Python带你从浅入深探究List
列表 Python中的列表(list)是最常用的数据类型之一. Python中的列表可以存储任意类型的数据,这与其他语言中的数组(array)不同. 被存入列表中的内容可称之为元素(element)或 ...
- 5分钟让你理解K8S必备架构概念,以及网络模型(中)
写在前面 在这用XMind画了一张导图记录Redis的学习笔记和一些面试解析(源文件对部分节点有详细备注和参考资料,欢迎关注我的公众号:阿风的架构笔记 后台发送[导图]拿下载链接, 已经完善更新): ...
- LVS跨网段DR模型
客户端IP地址:172.16.8.147 路由器服务器IP地址:172.16.8.167内网IP地址:192.168.1.3 一.将客户端的网关修改为路由服务器IP地址 vim ifcfg-ens33 ...
- linux自动化交互脚本expect详解set timeout 5是 意思是在expect语句中,5s后超时,不再作出选择。
linux自动化交互脚本expect详解 更新时间:2020年10月21日 10:13:20 作者:lendsomething 这篇文章主要介绍了linux自动化交互脚本expect的相 ...
- Ubuntu 获取升级信息失败。可能网络有问题
升级Ubuntu系统时遇到的这个问题, 原因是默认的源不是国内的,而且还可能导致下载慢等问题. 1.备份源 cd /etc/apt/ sudo cp sources.list sources.list ...
- 10.7 netstat:查看网络状态
netstat命令 用于显示本机网络的连接状态.运行端口和路由表等信息. netstat命令的参数选项及说明 -r 显示路由表信息,该功能类似于前面学过的route 和ip route-g 显示多播功 ...
- java 集合梳理
使用 processOn 画的java 集合图谱,应付面试应该可以了
- Python数学建模-01.新手必读
Python 完全可以满足数学建模的需要. Python 是数学建模的最佳选择之一,而且在其它工作中也无所不能. 『Python 数学建模 @ Youcans』带你从数模小白成为国赛达人. 1. 数学 ...