- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java 你知道什么是耦合、如何解(降低)耦合由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。模块间的耦合度是指模块之间的依赖关系,包括控制关系、调用关系、数据传递关系。模块间联系越多,其耦合性越强,同时表明其独立性越差( 降低耦合性,可以提高其独立性).
假如:当我去new一个对象的时候,而这个对象不存在,这个时候程序会报编译时异常,也就意味着程序连运行都运行不了,我们可以理解为他们的耦合度较高.
我们可以利用Java的反射技术,通过类定名,来进行反射创建对象,这个时候我们可以成功的避免编译时异常,并且保证了项目在这个时候还能正常运行.
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件,创建和获取三层对象的类就是工厂.
早期我们的 JDBC 操作,注册驱动时,我们为什么不使用 DriverManager 的 register 方法,而是采用 Class.forName 的方式?
1
2
3
4
5
6
7
8
9
10
11
|
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库进行改造,那将会是一个晴天霹雳.
但是,事与愿违,有些情况,还真的不太好解耦.
一个排序功能,对于大部分比较初级的程序猿来说,可能会写成这样:
1
|
sort(List<Integer> list)
|
这样就导致了一个问题所在,这个方法只能排序int型数据,如果下一个项目,需要用到对String进行排序,那就很尴尬,感觉明明要成功了,但是又差一点。对,就是差这一点,就是代码解耦的关键.
我们先要明确,我们需要做的是排序功能,在这个过程中,我们不可避免的需要使用2个数据的大小对比,而这个数据,可能是任何数据,也就是说,排序算法,我们是可以确定下来,做成不动的库,但是有一个数据大小匹配是我们无法做到的,或者说是库的耦合点,那怎么办呢?
我们就让使用我们这个功能块的人,告诉我们就行啦.
下面,我们参考Android库里面,有个排序的api 。
1
|
Collections.sort(List<T> list, Comparator<?
super
T> c);
|
这里,Comparator这个接口,就是使用者,需要实现,并且传递进去的接口。这样做,这个排序功能块就可以应用在任何场合,达到一次开发,受用终身的目的。是不是很神奇?
我们在开发时,经常会用到socket库,而socket最常用,最常用的一个功能就是:“连接->发送数据->接收数据->断开连接->回调结果” 。
所以,如果需要把这个流程,封装成一个功能块是很有意义的.
但是,这里有一个问题,是阻碍封装的,就是 "接收数据->断开连接",socket读取数据时,是一个inputStream,是个流,也就是说,其实,你并不知道,数据怎么样才算接收 完整/完毕 。
可能,有的协议,是通过头2个字节来判断整个数据长度 。
可能,有的协议是有帧头,帧尾,转义符来判断整个数据长度 。
…… 。
这让我们很头疼,那怎么 解决了,既然无法知道的东西,就让应用程序来告诉你呗。和上面一样,传入一个协议实现呗:
1
2
3
|
public
interface
UnZipDataAction{
// 返回null,表示未接收完全,继续接收,返回完整的byte[]就认为是已经接收完毕,把结果返回给应用,并且断开连接
byte
[] getRealData(
byte
[] recvData); ErrorCode getErrorCode(); }
|
这样,我们就把“连接->发送数据->接收数据->断开连接->回调结果”整个流程封装成了通用的功能块了.
解耦总结来说就是:你能知道的东西就写死,不知道但是又必须知道的东西,就让应用程序来告诉你,在java里面叫接口,在有些语言(OC, swift, C/C++)里面叫做代码段.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://blog.csdn.net/weixin_43888891/article/details/108289642 。
最后此篇关于Java 你知道什么是耦合、如何解(降低)耦合的文章就讲到这里了,如果你想了解更多关于Java 你知道什么是耦合、如何解(降低)耦合的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是一名优秀的程序员,十分优秀!