当前位置:网站首页>如何遵循“低耦合”设计原则?
如何遵循“低耦合”设计原则?
2022-07-24 17:41:00 【用户6557940】
类的设计需要遵循“高内聚、低耦合”的设计原则(或者说“高内聚、松耦合”)。什么是高内聚和低耦合:
- 高内聚:内聚是对软件系统中元素职责相关性和集中度的度量。如果元素具有高度相关的职责,除了这些职责内的任务,没有其它过多的工作,那么该元素就具有高内聚性。
- 低耦合:耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据
某种程度上理解,高内聚低耦合也是单一职责原则、迪米特法则的另一种体现。
结合项目上开发的经历,要将一个类设计为高内聚和低耦合的类,难的是实现和后期应对临时需求和corner case而增加的改动。当然,这也是没有良好设计种下的苦果。这种痛苦,会在某次增加feature时感受到,也可能是在重构的时候。总之,虽迟但到。
下面先看一个违背低耦合设计原则的示例。考虑如下一个示例:按钮控制电灯开关。
#include <iostream>
#define ON true
#define OFF false
class Lamp
{
public:
void on() {
// ...
}
void off() {
// ...
}
};
class Button
{
public:
Button(Lamp& lamp): mLamp(lamp){}
void touch() {
if (mState == ON) {
mState = OFF;
mLamp.off();
}
else {
mState = ON;
mLamp.on();
}
}
private:
Lamp& mLamp;
bool mState{OFF};
};这段代码是可以正常运行的,乍一看也没什么问题:
- 创建电灯Lamp的实例。
- 再创建Button的实例,并将Lamp对象的引用传给Button构造函数。
- 接下来只需调用Button对象的touch()函数,即可控制电灯的开关状态。
这有什么问题吗?当然有问题——将Lamp对象的引用传给Button。这样Button内部就知道了lamp。但问题是,我们去买一个按钮开关的时候,按钮开关知道电灯吗?按钮开关还可以控制洗衣机、风扇、中央空调……那我们是不是要把所有这些可用按钮开关控制的对象的引用都传给按钮开关呢?
Button需要知道这么多吗?显然不需要,不需要将Button与其控制的具体对象耦合起来。这显然违背了低耦合的设计原则。Button只需要控制一个可用开关控制的对象即可,至于这个对象具体是什么,Button无需了解。电灯也好,电视、风扇、空调、洗衣机也罢,它们同属于可用开关控制的对象,都具有“打开”和“关闭”两种状态,那么就让它们继承自一个共同的基类即可:
扩展地,如果一个Button可以同时控制多个对象,那么就在Button内部维护一个列表吧。
Jungle回去再翻看了下命令模式:作为程序员的你,必须要知道命令模式!
同样,代码实例中举的是开关控制点灯和电风扇的场景:
我原以为之前的设计会违背“低耦合”原则:Button内部直接控制Lamp和Fan。这就需要将Lamp对象和Fan对象以指针或引用(或者其他形式)传递给Button,然后Button内部操作这些对象。如果真这么设计,就犯了上面第二点中提到的错误。
这里的设计也符合“低耦合”的设计原则,只将一个抽象的Command传递给Button。Button并不知道Command细节,即,Button和Command并没有耦合在一起。如果要增加被控制的对象,那么直接继承自Command就可以了,无序改动已有的代码,这也符合开闭原则。
上面的示例也可以看出,降低耦合的办法之一是,引入抽象类(或者接口)。使对象依赖于抽象,而不是依赖于具体。这其实也是依赖倒转原则的要求。
第二种办法是,使用并严格遵循一些既有的设计模式,比如中介者模式、命令模式、适配器模式等。因为设计模式本身就是为了解决某类重复出现的问题而出现的一套成功或有效的解决方案。Just follow it!
另一种办法是引入分层。某种程度上来说,设计模式的使用,或者抽象类的引入,就是分层的一种体现。通过引入中间层,引入抽象层,来降低类与类之间的耦合。不过,引入分层,往往需要初期对项目有完整的规划。
温故而知新,就说这么多~
边栏推荐
- Use prometheus+grafana to monitor MySQL performance indicators
- com.mysql.cj.jdbc.exceptions. MySQLTransactionRollbackException: Deadlock found when trying to get lo
- (mandatory) override equals must override hashcode (principle analysis)
- Definition and storage of adjacency table and adjacency storage of directed graph and undirected graph
- How the computer accesses the Internet (IV) LAN and server response
- Introduction and use of Pinia
- C language custom types - Enumeration
- The most powerful programmer on the earth is equipped with a "three piece set". Do you know what it is?
- 1688/阿里巴巴按关键字搜索新品数据 API 使用说明
- 实习报告1——人脸三维重建方法
猜你喜欢

Mobile robot (IV) four axis aircraft

Separation and merging of channels

Logical operation of image pixels

Portfwd port forwarding

C language programming training topics: K characters in left-handed string, little Lele and Euclidean, printing arrow pattern, civil servant interview, poplar matrix

Socat port forwarding

分家后印象笔记过日子依然不好过,骚操作却不少

Wrote a few small pieces of code, broke the system, and was blasted by the boss

Colleges and universities have introduced 23 Philippine doctors with heavy funds, and the relevant departments have launched an investigation!

快速完成intelij idea的单元测试JUnit4设置
随机推荐
Two dimensional convolution -- use of torch.nn.conv2d
启发式合并(含一般式、树上启发式合并 例题)
船新 IDEA 2022.2 正式发布,新特性真香!
Link editing tips of solo blog posts illegal links
简单测试JS代码
Ipaylinks, a cross-border payment integration service, won the 3A Asia Award of treasury
Image information is displayed by browser: data:image/png; Base64, + image content
ShardingSphere数据库读写分离
Heuristic merging (including examples of general formula and tree heuristic merging)
深入解析著名的阿里云Log4j 漏洞
awk从入门到入土(17)awk多行写法
Awk from entry to earth (17) awk multiline writing
阿里巴巴/166获得店铺的所有商品 API使用说明
hcip第三天
Eth POS 2.0 stacking test network pledge process
es(1)
ShardingSphere数据库读写分离
Nearly 30 colleges and universities were named and praised by the Ministry of education!
C语言中的字符与字符串库函数的使用以及模拟实现
Internship report 1 - face 3D reconstruction method