Inversion of Control(控制反转)之 Dependency Injection(依赖注入)

本文介绍了依赖注入的设计模式,包括依赖倒置原则及其在代码解耦中的应用。探讨了构造器注入、属性注入及方法注入三种实现方式,并分析了各自的适用场景。

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

随着项目复杂度的提高,程序模块与模块间的关系犹如一碗意大利面。高耦合的代码会越来越难维护。所以松耦合的代码设计,会随着项目复杂度的提高而越来来越明显。

GoF说过,依赖倒置原则:高层模块不应该依赖地层模块,它们都应依赖于抽象;
抽象不依赖于细节,细节依赖抽象;

下面是一个没有依赖注入容器的情况下实现依赖注入:`public class Email

public class Email
{
    public void SendEmail()
    {
        // code
    }
}

public class Notification
{
    private Email _email;
    public Notification()
    {
        _email = new Email();
    }

    public void PromotionalNotification()
    {
        _email.SendEmail();
    }
}

Notification类依赖Email类,这违反了DIP,而且当我们要发送短信/保存到数据库的时候,我们还要改变Notification类。
我们使用抽象类/接口解耦

public interface IMessageService
{
    void SendMessage();
}
public class Email : IMessageService
{
    public void SendMessage()
    {
        // code
    }
}
public class Notification
{
    private IMessageService _iMessageService;

    public Notification()
    {
        _iMessageService = new Email();
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}

IMessageService 是一个接口,而Notification 类只要调用接口的方法/属性就可以了
同时,我们把Email对象的构造移到Notification 类外面去。

依赖注入模式可以实现。通常有三种方式
1. 构造器注入
2. 属性注入
3. 方法注入

构造器注入
最普遍的方式,当一个类需要另一个类的依赖的时候,我们通过构造函数来提供,现在我们这样写

public class Notification
{
    private IMessageService _iMessageService;

    public Notification(IMessageService _messageService)
    {
        this._iMessageService = _messageService;
    }
    public void PromotionalNotification()
    {
        _iMessageService.SendMessage();
    }
}

有几个好处:1.构造函数实现很简单,Notification类需要知道的很少。想要创建Notification实例的时候看构造函数就可以知道需要什么信息了。因此实现了松耦合。

属性注入

属性注入/setter注入比较不常见,当依赖可有可无的时候很有用。我们暴露一个可写的属性,允许客户提供不同的依赖实现,比如这样。

public class Notification
{
    public IMessageService MessageService
    {
        get;
        set;
    }
    public void PromotionalNotification()
    {

        if (MessageService == null)
        {
            // some error message
        }
        else
        {
            MessageService.SendMessage();

        }
    }
}

没有了构造函数。而用属性来替换,在PromotionalNotifications 方法里我们需要检查MessageService的值或者提供相应的服务。

方法注入
当依赖可以对于每个方法调用都不同的时候,我们可以通过一个方法参数来实现,比如我们的这个类还可以发送短信。我们就要使用方法注入

public class Email : IMessageService
{
    public void SendMessage()
    {
        // code for the mail send
    }
}
public class SMS : IMessageService
{
    public void SendMessage()
    {
        // code for the sms send
    }
}

public class Notification
{
    public void PromotionalNotification(IMessageService _messageService)
    {
        _messageService.SendMessage();
    }
}

IMessageService 接口在两个类中都实现了。我们可以提供不同的类对象作为参数,这样可以有不同的调用效果。我们可以使用这三种方法实现松耦合。取决于具体的情景

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值