解耦合

本文介绍了解耦合的概念及其重要性,通过排序功能和socket库两个例子,详细解释了如何通过接口设计实现代码的解耦合,使功能模块更加灵活、复用性更强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

广大程序猿同胞,经常会看到“解耦合”,也有很多人,会用这个词来装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++)里面叫做代码段。





### 半解耦合在SDD中的应用与解决方案 #### 什么是半解耦合? 半解耦合是一种介于完全解耦和紧耦合之间的状态,在这种状态下,模块之间仍然存在一定的依赖关系,但这些依赖被控制在一个可接受的范围内。这种方式能够平衡系统的灵活性和性能开销[^1]。 #### 半解耦合在软件设计描述(SDD)中的意义 在SDD中,半解耦合的设计通常用于满足特定的需求场景,比如当系统需要较高的运行效率而无法承受完全解耦带来的额外开销时。它允许开发者通过减少不必要的抽象层次来优化性能,同时保留一定程度的独立性和扩展性[^4]。 #### 实现方式 以下是几种常见的实现半解耦合的方式: 1. **接口限定** 使用有限制性的接口定义模块间通信协议,而不是开放所有的访问权限。这可以通过Java中的`interface`关键字或者C++中的纯虚函数实现。 ```java public interface DataProvider { String fetchData(); } class ConcreteDataProvider implements DataProvider { @Override public String fetchData() { return "Data from provider"; } } ``` 2. **事件驱动机制** 借助观察者模式或其他类似的事件监听器机制,让组件仅关注自己负责的任务而不直接调用其他组件的方法。这种方法有助于降低直接依赖的程度。 ```java import java.util.ArrayList; import java.util.List; abstract class EventListener { void onEvent(String eventData); } class EventHandler { private List<EventListener> listeners = new ArrayList<>(); void addListener(EventListener listener) { this.listeners.add(listener); } void notifyListeners(String event) { for (EventListener l : listeners) { l.onEvent(event); } } } ``` 3. **共享上下文对象** 创建一个轻量级的对象作为中介存储双方都需要的数据或配置参数,从而避免硬编码式的相互引用。 ```python class SharedContext: def __init__(self): self.data = {} context = SharedContext() module_a.set_context(context) module_b.get_data_from_context(context) ``` #### 解决方案案例 对于某些具体的应用场景,如物业管理系统[^3],可以采用上述提到的技术手段之一或多者的组合形式来进行半解耦合处理。例如,在登录验证过程中,前端页面不必知道具体的认证算法细节;而后端只需返回标准化的结果即可完成交互。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值