zoukankan      html  css  js  c++  java
  • 依赖倒置原则和依赖注入模式

    昨天读完了程杰的《大话设计模式》。。收获颇丰。深刻感到了设计模式的伟大。。对面向接口的编程也理解了不少。刚好看到codeproject上一篇将依赖倒置的。讲到了依赖注入的方式。仔细读了一下。翻译一遍加深认识。

    高耦合的代码随着项目复杂性的不断增加,最终会变成一碗碗的意大利面条啦。。二者通常是软件设计上的问题,如果一个类对另一个类的实现了解太多。当该类改变的时候会引起更多的改变。这违反了依赖倒置原则

    而松耦合的代码设计优良。随着时间流逝,代码复杂两增大,松耦合的好处会变得更加清晰,依赖注入模式是实现松耦合的一个好的办法,本文介绍在没有依赖注入容器的情况下实现依赖注入

    GoF说了,依赖倒置的原则:

    高层模块不应依赖于低层模块,他们都应该依赖于抽象
    抽象不依赖细节,细节依赖抽象

    刚开始写依赖倒置比较难,随着经验增长会有所改善,通过使高层模块依赖于抽象,依赖倒置成功解耦,依赖注入模式是该原则的一个实现。

    通常我们写出如下的代码:

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

    结论
    不难吧。通过构造器注入我们就可以降低耦合度了。因此,程序员一般会使用构造器注入。当然也可以混合着使用嘛。。

  • 相关阅读:
    页面抛出的"Unable to validate data"错误
    oracle的sqlnet.ora,tnsnames.ora,listener.ora三个配置文件 water
    Win7下完全卸载Oracle 11g water
    抛出多个异常 water
    【转】有关Oracle随机字符串的生成方法及具体应用 water
    【转】oracle 中随机取一条记录的两种方法 water
    【转】Oracle索引列NULL值引发执行计划该表的测试示例 water
    Oracle 取随机数 water
    dbms_output.put_line长度限制问题 water
    oracle 监听启动、停止、查看命令 water
  • 原文地址:https://www.cnblogs.com/lazycoding/p/2781384.html
Copyright © 2011-2022 走看看