依赖倒转原则:(Dependency Inversion Principle,DIP)是面向对象设计的五大基本原则之一。它的核心思想是:高层模块不应该依赖于低层模块,两者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。
解释
高层模块不应该依赖于低层模块:在软件系统中,通常有高层模块(业务逻辑层)和低层模块(数据访问层、工具类等)。传统设计中,高层模块往往依赖于低层模块的实现,这会导致高层模块难以改变或复用。依赖倒转原则则要求高层模块依赖于抽象(接口或抽象类)而不是具体的低层模块实现。
抽象不应该依赖于细节,细节应该依赖于抽象:抽象层(如接口或抽象类)应定义系统中稳定的、通用的行为,而具体的实现细节(低层模块的实现)则依赖于这些抽象。这样可以使得系统更加灵活,容易扩展和维护。
实现依赖倒转原则的方法:
依赖注入:通过构造函数注入、方法注入或属性注入的方式,把具体的实现类注入到高层模块中,而不是让高层模块直接创建或依赖于具体的实现类。
使用接口或抽象类:定义接口或抽象类来描述高层模块需要的行为,然后让低层模块实现这些接口或抽象类,从而解除高层模块与低层模块的耦合。
示例
假设有一个消息发送系统,最初只有邮件发送功能。为了满足依赖倒转原则,我们可以设计如下:
步骤一:底层模块设计
1.定义接口
public interface IMessageSender
{
public void SendMessage(string message);
}
2.继承接口
public class EmailSender : IMessageSender
{
public void SendMessage(string message)
{
Debug.Log("邮件发送");
}
}
public class SmsSender : IMessageSender
{
public void SendMessage(string message)
{
Debug.Log("短信发送");
}
}
高层模块:依赖注入
public class Notification
{
private readonly IMessageSender _messageSender;
// 通过构造函数注入具体的实现
public Notification(IMessageSender messageSender)
{
_messageSender = messageSender;
}
public void Notify(string message)
{
_messageSender.SendMessage(message);
}
}
调用:
public class Test_02 : MonoBehaviour
{
void Start()
{
// 依赖注入:在这里可以灵活地更换不同的实现
IMessageSender emailSender = new EmailSender();
Notification notification = new Notification(emailSender);
notification.Notify("你好!我是邮件");
}
}
总结
依赖倒转原则 强调模块之间的低耦合性,通过依赖抽象而不是具体实现,增强系统的可扩展性和维护性。它与开闭原则密切相关,遵循依赖倒转原则的设计往往更容易满足开闭原则。
通过依赖注入的方式,可以实现灵活的模块替换和扩展,避免了高层模块依赖具体实现导致的代码僵化问题。