如何理解高内聚、低耦合(附C#代码案例)
上一篇随笔提到了.NET常用的架构,其基本核心都是为了更好的完成高内聚、低耦合设计原则。便特意整理了此篇文章;下面我将讲解+反例+正例+C#实战代码,把这个知识点讲透,以便在日后的面试和工作中能直接回答和灵活使用。
一、搞懂:什么是高内聚、低耦合
1. 高内聚
- 一个类、一个模块只专注干一件事,职责单一,内部功能紧密关联,不掺杂无关逻辑。
- 简单说就是“自己的事自己干,不干别人的事”,比如订单类只处理订单业务,日志类只做日志记录,仓储类只负责数据读写,各司其职,不杂糅其他职责。
- 核心目的:让模块内部逻辑紧凑,改动单一职责的代码,不会牵扯无关功能,代码可读性、可维护性更强。‘’
2. 低耦合
- 模块与模块、类与类之间,依赖越少、关联越浅越好,尽量依赖抽象,不依赖具体实现。
- 简单说就是修改一个类或模块,不会影响到其他模块,哪怕替换某个功能,也只需要改动局部代码,不用牵一发而动全身。
- 核心目的:降低代码之间的关联性,方便扩展、替换、单元测试,提升代码的灵活性。
综上所述当面试官问“你怎么理解高内聚、低耦合”时,可以直接回答:
高内聚就是让单个模块/类职责单一,只需要做好一件事;低耦合就是减少模块之间的依赖,尽量依赖抽象而非具体实现。这两个原则结合起来,能让代码更易维护、易扩展、易测试,也是分层架构、面向对象设计的核心思想;
或者一句话总结:高内聚是对内管好自己,保证职责单一;低耦合是对外减少依赖,保证关联松散。
二、反面案例
点击查看代码
internal class Program
{
//硬编码数据库连接字符串
private readonly string _connectionString = "Server=.;Database=OrderDB;Trusted_Connection=True";
static void Main(string[] args)
{
Program program = new Program();
program.CreateOrder("123",100);
}
/// <summary>
/// 创建订单 打印日志 完成支付
/// </summary>
/// <param name="orderNo"></param>
/// <param name="amount"></param>
public void CreateOrder(string orderNo, decimal amount)
{
// 1. 直接写SQL数据访问逻辑(本该是DAL层的活)
Console.WriteLine($"执行SQL:插入订单 {orderNo},金额:{amount}");
// 2. 硬编码日志逻辑(本该是独立日志模块)
Console.WriteLine($"日志:订单{orderNo}创建成功");
// 3. 直接耦合支付逻辑(本该是独立服务)
PayOrder(orderNo);
}
/// <summary>
/// 支付方法,和订单业务耦合在一起
/// </summary>
private static void PayOrder(string orderNo)
{
Console.WriteLine($"订单{orderNo}支付完成");
}
}
上述代码案例在一个类包揽所有活,耦合度极高、内聚性极差,后期维护、扩展、测试都寸步难行。
问题实际分析:低内聚:一个类包揽订单业务、数据访问、日志记录、支付功能,职责混乱,完全违背单一职责。高耦合:硬编码数据库连接、直接依赖具体日志和支付逻辑,更换数据源、日志框架、支付方式,必须改动整个类。无法做单元测试,无法扩展,后期改一处代码,极易引发连锁bug。
三、正面案例
遵循单一职责,拆分模块,依赖抽象而非具体实现,实现高内聚、低耦合,贴合.NET分层架构思想。‘’
- 定义抽象接口(解耦核心)
面向接口编程,依赖抽象,不依赖具体实现,方便后续替换功能。
点击查看订单仓储接口
/// <summary>
/// 订单仓储接口
/// </summary>
public interface IOrderRepository
{
/// <summary>
/// 插入订单
/// </summary>
/// <param name="orderNo">订单号</param>
/// <param name="amount">金额</param>
public void InsertOrder(string orderNo, decimal amount);
}
点击查看日志接口
/// <summary>
/// 日志接口
/// </summary>
public interface ILogger
{
/// <summary>
/// 写日志
/// </summary>
public void LogInfo(string message);
}
点击查看支付类接口
/// <summary>
/// 支付服务接口
/// </summary>
public interface IPayService
{
/// <summary>
/// 支付
/// </summary>
/// <param name="orderNo">订单号</param>
public void Pay(string orderNo);
}
每个类只专注实现单一职责,互不干涉。
点击查看订单仓储实现
/// <summary>
/// 订单仓储实现:只负责数据读写(DAL层职责)
/// </summary>
public class OrderRepository : IOrderRepository
{
/// <summary>
/// 插入订单
/// </summary>
/// <param name="orderNo">订单号</param>
/// <param name="amount">金额</param>
public void InsertOrder(string orderNo, decimal amount)
{
//仅做数据访问,不掺杂业务逻辑
Console.WriteLine($"EF执行SQL:插入订单 {orderNo},金额:{amount}");
}
}
点击查看日志实现
/// <summary>
/// 日志接口实现
/// </summary>
public class Logger : ILogger
{
/// <summary>
/// 写入日志
/// </summary>
/// <param name="message">内容</param>
public void LogInfo(string message)
{
Console.WriteLine($"写入日志:{message}");
}
}
点击查看支付类接口实现
/// <summary>
/// 支付服务实现
/// </summary>
public class PayService: IPayService
{
/// <summary>
/// 支付
/// </summary>
/// <param name="orderNo">订单号</param>
public void Pay(string orderNo)
{
Console.WriteLine($"订单{orderNo}支付成功");
}
}
- 业务逻辑层(依赖抽象,低耦合)
订单服务只处理核心业务逻辑,通过构造函数注入依赖,不依赖具体实现类,彻底解耦。
点击查看订单业务服务
/// <summary>
/// 订单业务服务:只处理订单核心业务(BLL层职责)
/// </summary>
public class OrderService
{
private readonly IOrderRepository _orderRepository;
private readonly ILogger _logger;
private readonly IPayService _payService;
/// <summary>
/// 依赖注入,面向接口编程,低耦合
/// </summary>
public OrderService(IOrderRepository orderRepository, ILogger logger, IPayService payService)
{
_orderRepository = orderRepository;
_logger = logger;
_payService = payService;
}
/// <summary>
/// 仅处理订单业务,相关业务只需执行相应模块方法,不掺杂其他无关逻辑
/// </summary>
public void CreateOrder(string orderNo, decimal amount)
{
// 调用数据访问
_orderRepository.InsertOrder(orderNo, amount);
// 记录日志
_logger.LogInfo($"订单{orderNo}创建完成");
// 调用支付
_payService.Pay(orderNo);
}
}
四、总结
高内聚是对内管好自己,保证职责单一;低耦合是对外减少依赖,保证关联松散。
不管是三层架构、七层整洁架构,还是DDD、微服务,核心都是为了实现高内聚、低耦合,让代码更健壮、更易维护,这也是作为后端开发者必备的设计思维。

浙公网安备 33010602011771号