Java 你知道什么是耦合、如何解(降低)耦合

目录
  • 什么是耦合性
  • 什么是程序间的耦合
  • 如何解耦
  • 工厂模式解耦
  • 案例
    • 原因就是:
    • 解决思路:
  • 解耦合
    • 这里,我们先举个栗子,比如排序
    • 我们再举个栗子,socket

什么是耦合性

耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性)。

什么是程序间的耦合

假如:当我去new一个对象的时候,而这个对象不存在,这个时候程序会报编译时异常,也就意味着程序连运行都运行不了,我们可以理解为他们的耦合度较高。

如何解耦

我们可以利用Java的反射技术,通过类定名,来进行反射创建对象,这个时候我们可以成功的避免编译时异常,并且保证了项目在这个时候还能正常运行。

工厂模式解耦

在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件,创建和获取三层对象的类就是工厂。

案例

早期我们的 JDBC 操作,注册驱动时,我们为什么不使用 DriverManager 的 register 方法,而是采用 Class.forName 的方式?

public class JdbcDemo1 {
 public static void main(String[] args) throws Exception {
 //1.注册驱动
 //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
 Class.forName("com.mysql.jdbc.Driver");
 //2.获取连接
 //3.获取预处理 sql 语句对象
 //4.获取结果集
 //5.遍历结果集
 }
}

原因就是:

我们的类依赖了数据库的具体驱动类(MySQL),如果这时候更换了数据库品牌(比如 Oracle),需要修改源码来重新数据库驱动。这显然不是我们想要的。

解决思路:

当是我们讲解 jdbc 时,是通过反射来注册驱动的,代码如下:

Class.forName("com.mysql.jdbc.Driver");//此处只是一个字符串

此时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除 mysql 的驱动 jar 包,依然可以编译(运行就不要想了,没有驱动不可能运行成功的)。同时,也产生了一个新的问题,mysql 驱动的全限定类名字符串是在 java 类中写死的,一旦要改还是要修改源码。解决这个问题也很简单,使用配置文件配置。

以上只是说的解耦的一种思维,方便大家理解。

解耦的核心思想:若要减少代码的耦合度,一定要尽量做到各个功能的代码不能交叉编写,编写封闭的代码。

解耦合

广大程序猿同胞,经常会看到“解耦合”,也有很多人,会用这个词来装X,但是,实际真正能理解的人,并不多。接下来,带大家深入浅出的走一遍,如何解耦合。

首先,我们要知道,为什么要解耦合:通常,我们做一个项目,会用到很多基础功能块,比如xxx通信协议,xxxView等等,我们会把这种功能块封装成一个库,如果这个库,只能在这个指定的项目运行,这就叫高耦合,这就导致了,如果下次再次遇到一个类似的项目,需要用到同样功能的功能块时,你会要做很多重复工作。假设,每次使用json时,你都要对json库进行改造,那将会是一个晴天霹雳。

但是,事与愿违,有些情况,还真的不太好解耦。

这里,我们先举个栗子,比如排序

一个排序功能,对于大部分比较初级的程序猿来说,可能会写成这样:

sort(List<Integer> list)

这样就导致了一个问题所在,这个方法只能排序int型数据,如果下一个项目,需要用到对String进行排序,那就很尴尬,感觉明明要成功了,但是又差一点。对,就是差这一点,就是代码解耦的关键。

我们先要明确,我们需要做的是排序功能,在这个过程中,我们不可避免的需要使用2个数据的大小对比,而这个数据,可能是任何数据,也就是说,排序算法,我们是可以确定下来,做成不动的库,但是有一个数据大小匹配是我们无法做到的,或者说是库的耦合点,那怎么办呢?

我们就让使用我们这个功能块的人,告诉我们就行啦。

下面,我们参考Android库里面,有个排序的api

Collections.sort(List<T> list, Comparator<? super T> c);

这里,Comparator这个接口,就是使用者,需要实现,并且传递进去的接口。这样做,这个排序功能块就可以应用在任何场合,达到一次开发,受用终身的目的。是不是很神奇?

我们再举个栗子,socket

我们在开发时,经常会用到socket库,而socket最常用,最常用的一个功能就是:“连接->发送数据->接收数据->断开连接->回调结果”

所以,如果需要把这个流程,封装成一个功能块是很有意义的。

但是,这里有一个问题,是阻碍封装的,就是 "接收数据->断开连接",socket读取数据时,是一个inputStream,是个流,也就是说,其实,你并不知道,数据怎么样才算接收 完整/完毕

可能,有的协议,是通过头2个字节来判断整个数据长度

可能,有的协议是有帧头,帧尾,转义符来判断整个数据长度

……

这让我们很头疼,那怎么 解决了,既然无法知道的东西,就让应用程序来告诉你呗。和上面一样,传入一个协议实现呗:

public interface UnZipDataAction{
// 返回null,表示未接收完全,继续接收,返回完整的byte[]就认为是已经接收完毕,把结果返回给应用,并且断开连接
 byte[] getRealData(byte[] recvData); ErrorCode getErrorCode(); }

这样,我们就把“连接->发送数据->接收数据->断开连接->回调结果”整个流程封装成了通用的功能块了。

解耦总结来说就是:你能知道的东西就写死,不知道但是又必须知道的东西,就让应用程序来告诉你,在java里面叫接口,在有些语言(OC, swift, C/C++)里面叫做代码段。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java Web项目前端规范(采用命名空间使js深度解耦合)

    没有规矩不成方圆,一个优秀的代码架构不仅易于开发和维护,而且是一门管理与执行的艺术. 这几年来经历了很多项目,对代码之间的强耦合及书写不规范,维护性差等问题深恶痛绝.在这里,通过仔细分析后,结合自己的编码习惯总结了一套适用于javaweb项目的前端书写规范,与大家分享一下. ps:感谢阿海的创意,后期整理如下(附文件下载): 一.项目结构 这里和其他项目区别不大,我将模板抽离出来,更容易分析和理解: 解释一下:js主要包括extends(引入第三方的js).module(项目模块自己的js).l

  • java Spring松耦合高效应用简单实例分析

    java Spring松耦合 面向对象的概念,是一个很好的设计来打破系统进入一个组可重用的对象.然而,当系统变大,尤其是在Java项目,庞大的对象依赖关系将一直紧密耦合引起对象难以管理或修改.在这种情况下,可以使用Spring框架作为一个核心模块轻松高效地管理所有的对象依赖. 输出生成器的例子 让我们来看一个例子,假设你的项目有一个函数输出的内容,以CSV或JSON格式.您的代码可能看起来像下面的例子: File : IOutputGenerator.java – 输出生成器接口 package

  • java的接口解耦方式

    目录 java的接口解耦方式 举例子 java接口解耦效果的理解 先看一段代码 java的接口解耦方式 我只想把抽象的东西说的具体,或者说,听起来简单些,明白些... 学过java的人都知道,java是单继承的,也就是说一个class只能继承一个类. 例如我们想制作一台有播放器的手机,那么我们先得制作一个播放器吧,再把播放器放进手机里.在java会怎么实现呢?如果使用继承,我们会先创建一个播放器类,播放器类里面含有播放歌曲功能(方法),创建一个手机类继承播放器类,重写播放器的播歌功能(不重写的话

  • 高内聚低耦合原则_动力节点Java学院整理

    一.什么是耦合度 软件设计中通常用耦合度和内聚度作为衡量模块独立程度的标准.划分摸块的一个准则就是高内聚低耦合. 耦合度(Coupling)是对模块间关联程度的度量.耦合的强弱取决与模块间接口的复杂性.调用模块的方式以及通过界面传送数据的多少. 模块间的耦合度是指模块之间的依赖关系,包括控制关系.调用关系.数据传递关系.模块间联系越多,其耦合性越强,同时表明其独立性越差.降低模块间的耦合度能减少模块间的影响,防止对某一模块修改所引起的"牵一发动全身"的水波效应,保证系统设计顺利进行.

  • Java 你知道什么是耦合、如何解(降低)耦合

    目录 什么是耦合性 什么是程序间的耦合 如何解耦 工厂模式解耦 案例 原因就是: 解决思路: 解耦合 这里,我们先举个栗子,比如排序 我们再举个栗子,socket 什么是耦合性 耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量.模块间的耦合度是指模块之间的依赖关系,包括控制关系.调用关系.数据传递关系.模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性). 什么是程序间的耦合 假如:当我去new一个对象的时候,而这个对象不存在,这个时候程序会报编译

  • java 使用BeanFactory实现service与dao层解耦合详解

    目录 BeanFactory实现service与dao层解耦合 整体的实现思路是 DAO层实现类CreatFactory.java BeanFactory实现service与dao层解耦合 在实际网站开发过程中,在service会new一个dao从而调用该dao中的方法,如下代码,但是一旦更换数据库需要改变dao的指向,此时就需要重新部署新的项目 UserDao UserDao=new UserDaoImpl(); 在本文中使用BeanFactory的方式,在xml中配置dao的指向,一旦发生变

  • Java设计模式之23种设计模式详解

    一.什么是设计模式 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是

  • Java微服务开发之Swagger详解

    目录 一.Swagger的作用和概念 1.Swagger 的优势 2.SwaggerUI 特点 2.SpringBoot集成Swagger 3.配置Swagger 4.实体配置 5.其他皮肤 一.Swagger的作用和概念 ​ 官方地址:https://swagger.io/ ​ Swagger 是一个规范且完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务以及 集成Swagger自动生成API文档. ​ Swagger 的目标是对 REST API 定义一个标准且和

  • Java Spring Boot消息服务万字详解分析

    目录 消息服务概述 为什么要使用消息服务 异步处理 应用解耦 流量削峰 分布式事务管理 常用消息中间件介绍 ActiveMQ RabbitMQ RocketMQ RabbitMQ消息中间件 RabbitMQ简介 RabbitMQ工作模式介绍 Work queues(工作队列模式) Public/Subscribe(发布订阅模式) Routing(路由模式) Topics(通配符模式) RPC Headers RabbitMQ安装以及整合环境搭建 安装RabbitMQ 下载RabbitMQ 安装R

  • Java设计模式之职责链模式详解

    目录 前言 一.职责链模式的定义与特点 二.职责链模式的结构 三.职责链模式案例 前言 本文简单介绍了设计模式的一种--职责链模式  一.职责链模式的定义与特点 定义: 为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链:当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止. 比如我们的审批制度,低等级的审批不了的,交给上一级审批,依次类推,直到审批结束. 在责任链模式中,客户只需要将请求发送到责任链上即可,无须关心请求的处

  • Java设计模式之迪米特原则精解

    目录 1.什么是迪米特原则? 2.违反迪米特原则代码案例 3.遵守迪米特原则代码案例 4.迪米特原则的注意事项 1.什么是迪米特原则? 一个对象应该对其他对象保持最少的了解. 类与类关系越密切,耦合度越大. 迪米特法则(Demeter Principle)又叫最少知道原则,即一个类对自己依赖的类知道的越少越好.也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部.对外除了提供的public方法,不对外泄露任何信息. 迪米特法则还有个更简单的定义:只与直接的朋友通信. 直接的朋友:每个

  • Java设计模式之里氏替换原则精解

    1.什么是里氏替换原则? 我们都知道,在面向对象编程中有三大特性(封装.继承.多态),在这里我们来说 继承 这个东西. 继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些契约,但是如果子类对这些已经实现的方法任意修改,就会对整个继承体系造成破坏. 也就是说:继承在给程序设计带来便利的同时,也带来了弊端.比如使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到

  • Java装饰者模式的示例详解

    目录 定义 案例 需求 方案 分析 使用场景 知识点补充 定义 装饰者模式:在不改变原有对象的基础之上,动态的将功能附加到对象上,提供了继承更有弹性的替代方案,也体现了开闭原则 案例 需求 一个人去咖啡店点了一杯卡布奇诺,加了一份热牛奶 方案 定义咖啡基类 public abstract class Coffee { private String desc; private float price; public abstract float cost(); public String getD

  • Java设计模式之工厂模式案例详解

    目录 分类 案例 需求 方案一:简单工厂模式 方案二:工厂方法模式 方案三:抽象工厂模式 对比分析 总结 分类 1.简单工厂模式 2.工厂方法模式 3.抽象工厂模式 案例 需求 根据蛋糕的不同口味,分别创建苹果味和香蕉味的蛋糕实例 方案一:简单工厂模式 定义蛋糕父类 /** * 蛋糕 * @author:liyajie * @createTime:2022/2/14 10:17 * @version:1.0 */ public class Cake { } 定义苹果味的蛋糕 /** * 苹果蛋糕

随机推荐