内聚、耦合

内聚、耦合

内聚

内聚的种类(从低到高)

内聚性(Cohesion)衡量模块内部各部分之间的关联程度,高内聚是优秀设计的核心原则。以下是7种内聚类型(按质量从低到高排序),附代码示例说明:

1. 偶然内聚(Coincidental Cohesion)

特点:模块内代码无逻辑关联,仅因巧合被放在一起。

示例:一个工具类包含随机方法:

class Utils {

public static void printDate() { ... } // 打印日期

public static void encryptData() { ... } // 加密数据

public static void connectDB() { ... } // 连接数据库

}

问题:方法之间毫无关系,难以维护。

2. 逻辑内聚(Logical Cohesion)

特点:代码通过参数控制执行不同逻辑,但操作无本质联系。

示例:用一个函数处理多种文件操作:

def file_operation(operation, filename):

if operation == "read":

return read_file(filename)

elif operation == "delete":

return delete_file(filename) # 删除和读取逻辑无关

问题:调用者需知道内部逻辑,新增操作需修改函数。

3. 时间内聚(Temporal Cohesion)

特点:代码因同一时间段执行被放在一起,但无功能关联。

示例:程序初始化时调用的函数:

void startup() {

init_logger(); // 初始化日志

load_config(); // 加载配置

clear_cache(); // 清空缓存

}

问题:虽在启动时调用,但各函数职责分离更合理。

4. 过程内聚(Procedural Cohesion)

特点:代码按特定流程顺序执行,但无数据传递。

示例:用户注册流程:

function registerUser() {

validateInput(); // 验证输入

createUser(); // 创建用户

sendWelcomeEmail(); // 发邮件(依赖前两步成功)

}

改进方向:可拆分为更小单元(如验证服务、邮件服务)。

5. 通信内聚(Communicational Cohesion)

特点:代码操作相同数据,但无严格功能联系。

示例:处理用户数据的函数:

class UserData {

public void updateProfile(User user) { ... } // 更新资料

public void logActivity(User user) { ... } // 记录活动

}

优点:比前几种内聚性更高,但仍可细分(如日志模块独立)。

6. 顺序内聚(Sequential Cohesion)

特点:代码前一步输出是后一步输入,形成流水线。

示例:数据处理流水线:

def process_data(data):

cleaned = clean_data(data) # 清洗数据

transformed = transform(cleaned) # 转换格式

save_to_db(transformed) # 存储结果

优点:逻辑清晰,符合单一职责原则。

7. 功能内聚(Functional Cohesion)★ 理想状态

特点:模块仅完成单一功能,所有代码紧密相关。

示例:计算圆的面积:

class Circle {

private double radius;

public double calculateArea() {

return Math.PI * radius * radius; // 只做一件事

}

}

优点:高复用性、低耦合、易测试维护。

总结对比表

内聚类型

关键特征

质量

示例

偶然内聚

代码随机拼凑

最差

工具类包含无关方法

逻辑内聚

通过参数分支执行不同逻辑

多合一文件操作函数

时间内聚

同一时间段执行但无功能关联

较低

程序初始化函数

过程内聚

按流程顺序执行但无数据传递

中等

用户注册流程

通信内聚

操作相同数据但功能独立

良好

用户数据更新和日志记录

顺序内聚

前一步输出是后一步输入

优秀

数据清洗→转换→存储流水线

功能内聚

仅完成单一功能

最优

计算圆的面积

耦合

无数的鸡控制在外公的容器里(无、数、记、控制、外、公、内容)

耦合

耦合是指软件模块之间相互依赖的程度,耦合度越低,系统越容易维护和修改。以下是常见的耦合类型及Java代码示例:

1. 无耦合/无依赖 (No Coupling)

两个模块之间没有任何依赖关系。

// Module A

public class Calculator {

public int add(int a, int b) {

return a + b;

}

}

// Module B

public class Logger {

public void log(String message) {

System.out.println(message);

}

}

2. 数据耦合 (Data Coupling)

模块之间通过参数传递基本数据类型进行通信。

public class OrderProcessor {

public void processOrder(String orderId, double amount) {

// 处理订单逻辑

}

}

public class Main {

public static void main(String[] args) {

OrderProcessor processor = new OrderProcessor();

processor.processOrder("ORD123", 99.99);

}

}

3. 标记耦合 (Stamp Coupling)

模块之间通过传递复合数据结构(如对象)进行通信,但只使用其中部分数据。

public class Customer {

private String name;

private String address;

private String phone;

// getters and setters

}

public class EmailService {

public void sendWelcomeEmail(Customer customer) {

// 只使用customer的name和email

String emailContent = "Dear " + customer.getName() + ", welcome!";

// 发送邮件...

}

}

4. 控制耦合 (Control Coupling)

一个模块通过传递控制信息(如标志)来影响另一个模块的内部逻辑。

public class ReportGenerator {

public void generateReport(boolean isDetailed) {

if (isDetailed) {

generateDetailedReport();

} else {

generateSummaryReport();

}

}

// 其他方法...

}

public class Main {

public static void main(String[] args) {

ReportGenerator generator = new ReportGenerator();

generator.generateReport(true); // 控制生成详细报告

}

}

5. 外部耦合 (External Coupling)

模块依赖于外部系统或工具的接口。

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

public class DatabaseAccess {

public Connection getConnection() throws SQLException {

return DriverManager.getConnection(

"jdbc:mysql://localhost:3306/mydb", "user", "password");

}

}

6. 公共耦合 (Common Coupling)

多个模块共享同一个全局数据。

public class GlobalConfig {

public static String DATABASE_URL = "jdbc:mysql://localhost:3306/mydb";

public static int TIMEOUT = 30;

}

public class OrderService {

public void processOrder() {

String url = GlobalConfig.DATABASE_URL;

// 使用全局配置

}

}

public class UserService {

public void getUser() {

String url = GlobalConfig.DATABASE_URL;

// 使用全局配置

}

}

7. 内容耦合 (Content Coupling)

一个模块直接修改或依赖另一个模块的内部数据或实现细节。

public class BankAccount {

public double balance; // 不应该公开字段

// 其他方法...

}

public class AccountManager {

public void manipulateAccount(BankAccount account) {

account.balance += 1000; // 直接修改另一个类的内部字段

}

}

最佳实践

在Java开发中,应该:

尽量使用接口耦合而非实现耦合

遵循依赖倒置原则(DIP)

使用依赖注入(DI)来降低耦合

// 接口耦合示例

public interface MessageService {

void sendMessage(String message);

}

public class EmailService implements MessageService {

@Override

public void sendMessage(String message) {

// 发送邮件实现

}

}

public class NotificationService {

private MessageService messageService;

// 依赖注入

public NotificationService(MessageService messageService) {

this.messageService = messageService;

}

public void notifyUser(String message) {

messageService.sendMessage(message);

}

}

低耦合的设计可以使系统更易于维护、测试和扩展。

相关推荐

衄血是什么意思
约彩365手机下载安装

衄血是什么意思

📅 11-09 👁️ 2843
枝多少|永續纖維手札
365bet备用在线

枝多少|永續纖維手札

📅 09-24 👁️ 8349
诺基亚4g手机有哪些
365bet备用在线

诺基亚4g手机有哪些

📅 10-17 👁️ 7667
怪物猎人曙光和破晓哪个好
约彩365手机下载安装

怪物猎人曙光和破晓哪个好

📅 11-22 👁️ 3770
商业特许经营备案管理办法
约彩365手机下载安装

商业特许经营备案管理办法

📅 09-19 👁️ 1936
手机比价软件
365bet备用在线

手机比价软件

📅 07-12 👁️ 6631
银行审核资金来源需要多久
约彩365手机下载安装

银行审核资金来源需要多久

📅 07-30 👁️ 5332
股票分红记录查询方法:散户实用攻略与工具推荐
365bet备用在线

股票分红记录查询方法:散户实用攻略与工具推荐

📅 10-09 👁️ 4090
iPhone XR手机WiFi断流是什么原因
365bet备用在线

iPhone XR手机WiFi断流是什么原因

📅 09-01 👁️ 1188