揭开均线系统的神秘面纱

by Sankalp Bhatia

通过Sankalp Bhatia

揭开依赖注入的神秘面纱,并通过此快速介绍了解它的实际应用 (Demystify Dependency Injection and see it in action with this quick intro)

Dependency Injection (DI) is a topic which I found a little difficult to grasp during my initial days as a software developer. I just could not find a good definition of the term.

依赖注入(DI)是一个主题,在我作为软件开发人员的最初几天,我发现它有点难以掌握。 我只是找不到一个很好的定义。

In this article, I’ve tried to put my understandings of it in fairly simple language. It is intended for people starting out with DI, or those who just want to get a little more insight.

在本文中,我试图用相当简单的语言表达对它的理解。 它适用于刚开始使用DI的人或只想获得更多见识的人。

什么是依赖注入? (What is Dependency Injection?)

First things first: what is it? Dependency Injection, like so much other software development jargon, is a fancy term for a rather simple concept.

第一件事:什么? 像其他许多软件开发术语一样,依赖注入是一个相当简单的概念的花哨术语。

The definition which I found most useful is:

我发现最有用的定义是:

Dependency injection means giving an object its instance variables.

依赖注入意味着给对象一个实例变量。

That’s it. Providing (injecting) dependencies for a class. Simple right? Indeed.

而已。 提供(注入)类的依赖关系。 简单吧? 确实。

Now, there are three ways of providing a class its dependencies in Java. All of them achieve…(coughs) Dependency Injection.

现在,有三种方法可以在Java中为类提供其依赖项。 他们都实现了……(咳嗽)依赖注入。

They are:

他们是:

  • Constructors建设者
  • Setters二传手
  • Directly setting public fields直接设置公共领域

让我们看看依赖注入的作用 (Let’s see Dependency Injection in action)

I have an application class named MyMessagePublisher which has a dependency on a certain EmailService class.

我有一个名为MyMessagePublisher的应用程序类,该类与某个EmailService类有关。

使用构造函数的依赖注入: (Dependency Injection using Constructor:)

public class MyMessagePublisher {    private EmailService emailService = null;        public MyMessagePublisher(EmailService emailService){        this.emailService = emailService;    }}

See what the constructor is doing there? It is telling MyMessagePublisher to use the EmailService provided by it. The class instantiating MyMessagePublisher should provide (inject) an EmailService instance (using the constructor) to be used by MyMessagePublisher. Something like this:

看看构造函数在那里做什么? 它告诉MyMessagePublisher使用它提供的EmailService。 实例化MyMessagePublisher的类应提供(注入)MyMessagePublisher要使用的EmailService实例(使用构造函数)。 像这样:

EmailService emailService = new EmailService();MyMessagePublisher myMessagePublisher =                            new MyMessagePublisher(emailService);

Good job, Constructor!

干得好,建设者!

使用Setter进行依赖注入: (Dependency Injection using Setter:)

public class MyMessagePublisher {    private EmailService emailService = null;    public MyMessagePublisher() {    }    public setEmailService(EmailService emailService) {        this.emailService = emailService;    }}

What’s going on here? The class using MyMessagePublisher can now set the EmailService which they want to use. Something like this:

这里发生了什么? 现在,使用MyMessagePublisher的类可以设置他们要使用的EmailService。 像这样:

MyMessagePublisher myMessagePublisher = new MyMessagePublisher();myMessagePublisher.setEmailService(new EmailService());

Good job, Setter!

干得好,塞特犬!

通过直接设置公共字段进行依赖注入 (Dependency Injection by directly setting public fields)

Never do this!! If you have reached this far reading this article, I believe you know that this approach is evil.

永远不要这样做! 如果您到目前为止已经阅读了本文,那么我相信您知道这种方法是邪恶的。

依赖注入的好处 (Benefits of Dependency Injection)

I’ll start this section by explaining what we miss out on if we do not use DI.

我将从解释不使用DI会错过的内容开始本节。

Consider this code. I have defined the EmailService and MyMessagePublisher classes. MyMessagePublisher itself instantiates an EmailService object instead of using the DI techniques mentioned above.

考虑一下此代码。 我已经定义了EmailService和MyMessagePublisher类。 MyMessagePublisher本身将实例化EmailService对象,而不使用上述DI技术。

public class EmailService {        public void sendEmail(String message, String receiver){        System.out.println("Email sent to " + receiver);    }}
public class MyMessagePublisher {    private EmailService emailService = new EmailService();    public void processMessages(String message, String receiver){        this.emailService.sendEmail(message, receiver);    }}

The above code has some limitations:

上面的代码有一些限制:

  1. If EmailService initialization logic changes (it takes a constructor parameter to initialize), we would need to make changes to MyMessagePublisher class along with everywhere else in the codebase where we are using EmailService without DI.如果EmailService的初始化逻辑发生了变化(需要使用构造函数参数进行初始化),我们将需要对MyMessagePublisher类以及我们使用无DI的EmailService的代码库中的其他所有地方进行更改。
  2. It has tight coupling. Let’s say we want to move away from sending emails and instead start sending SMSs. We will then have to write a new publisher class.它具有紧密的耦合。 假设我们要远离发送电子邮件,而是开始发送SMS。 然后,我们将不得不编写一个新的发布者类。
  3. This code is not testable. We will be sending emails to everyone while unit testing MyMessagePublisher class.此代码不可测试。 在对MyMessagePublisher类进行单元测试时,我们将向所有人发送电子邮件。

This is the solution I propose:

这是我建议的解决方案:

public class EmailService implements MessageService {    @Override    public void sendMessage(String message, String receiver) {        //logic to send email    }}
public class SMSService implements MessageService {    @Override    public void sendMessage(String message, String receiver) {        //logic to send SMS    }
public interface MessageService {    void sendMessage(String message, String receiver);}
public class MyMessagePublisher {    private MessageService messageService;        public MyMessagePublisher(MessageService messageService){        this.messageService = messageService;    }        @Override    public void processMessages(String msg, String rec){        this.service.sendMessage(msg, rec);    }}

This implementation overcomes all three limitations mentioned above.

此实现克服了上述所有三个限制。

  • EmailService (or MessageService) initialization logic moves to the module initializing MyMessagePublisherEmailService(或MessageService)初始化逻辑移至初始化MyMessagePublisher的模块
  • We can move to a different implementation of MessageService which sends SMS without changing code in MyMessagePublisher我们可以转到MessageService的其他实现,该实现发送SMS而不更改MyMessagePublisher中的代码
  • The code is testable. We can use a dummy implementation of MessageService while unit testing MyMessagePublisher该代码是可测试的。 在单元测试MyMessagePublisher时,我们可以使用MessageService的虚拟实现

Sweet. We have achieved DI using Constructors of our classes. Easy right? But there are some shortcomings here as well.

甜。 我们已经使用我们的类的构造函数实现了DI。 容易吧? 但是这里也有一些缺点。

香草依赖注射的问题 (Issues with Vanilla Dependency Injection)

When does this become a problem? When the code grows.

什么时候会成为问题? 当代码增长时

So what are the alternatives? Dependency Injection Containers (Spring, Guice, Dagger, and so on).

那么还有哪些选择呢? 依赖注入容器 (Spring,Guice,Dagger等)。

Let’s try to answer the questions above in more detail.

让我们尝试更详细地回答上述问题。

Consider the code below. We are designing an AllInOneApp which offers multiple services like booking movie tickets, recharging prepaid connections, transferring money, and online shopping.

考虑下面的代码。 我们正在设计一个AllInOneApp,它提供多种服务,例如预订电影票,为预付费连接充值,转账和在线购物。

public class BookingService {    private SlotsManager slotsManager;    private MyMessagePublisher myMessagePublisher; //Looks familiar?}
public class AllInOneApp  {    BookingService bookingService; // Class above    RechargeService rechargeService;    MoneyTransferService moneyTransferService;    ShoppingService shoppingService;}

AllInOneApp needs four dependencies to be initialized. Let’s use vanilla Dependency Injection using Constructor here and instantiate the AllInOneApp class.

AllInOneApp需要初始化四个依赖项。 让我们在此处使用使用构造函数的原始依赖注入,并实例化AllInOneApp类。

public static void main(String[] args) {
AllInOneApp allInOneApp = new AllInOneApp(                new BookingService(new SlotsManager(),                                   new MyMessagePublisher(                                              new EmailService())),                 new RechargeService(...),                 new MoneyTransferService(..),                new ShoppingService(...));
}

This looks messy. Can we identify the problems here? A couple of them are:

看起来很乱。 我们可以在这里找到问题吗? 其中一些是:

  • The class initializing AllInOneApp needs to know the logic to construct all the dependency classes as well. This is cumbersome when writing code in any decent sized project. Managing all these instances by ourselves is not what we want to do while writing business specific code.初始化AllInOneApp的类也需要知道构造所有依赖项类的逻辑。 在任何大小合适的项目中编写代码时,这很麻烦。 编写业务特定代码时,我们不想自己管理所有这些实例。
  • Although I have seen people prefer this kind of DI, I personally believe this code is less readable as compared to this:尽管我看到人们更喜欢这种DI,但我个人认为与以下代码相比,此代码的可读性较差:
AllInOneApp myApp = SomeDIContainer.getInstance(AllInOneApp.class);

If all the components use DI, somewhere in the system some class or factory must know what to inject into all these components (AllInOneApp, BookingService, MessageService etc).

如果所有组件都使用DI,则系统中的某个类或工厂必须知道要向所有这些组件(AllInOneApp,BookingService,MessageService等)中注入什么。

This is where Dependency Injection containers come into picture. It is called a container and not a factory because the container often takes on more responsibility than just instantiating objects and injecting dependencies.

这是Dependency Injection容器出现的地方 。 之所以称为容器而不是工厂,是因为容器通常承担的责任不仅仅是实例化对象和注入依赖关系。

DI containers let us define what components are to be initiated and what dependencies to be injected in those components. We can also configure other instantiation features, like the object being a singleton or getting created every time it is requested.

DI容器使我们可以定义要启动哪些组件以及要在这些组件中注入哪些依赖项。 我们还可以配置其他实例化功能,例如对象是单例对象,或在每次请求时创建。

I will be writing another article explaining the usage of one of the popularly used DI Containers, Google Guice, which will have a hands on practice section as well. I will update this story with it’s link soon. I will now leave you with this user guide which is a good place to start.

我将写另一篇文章,解释一种常用的DI容器Google Guice的用法,该工具还将在实践部分进行介绍。 我将通过链接更新此故事。 现在,我将为您提供本用户指南 ,这是一个很好的起点。

Thank you for reading :)

谢谢您的阅读:)

翻译自: https://www.freecodecamp.org/news/demystifying-dependency-injection-49d4b6fe6536/

揭开均线系统的神秘面纱

揭开均线系统的神秘面纱_揭开依赖注入的神秘面纱,并通过此快速介绍了解它的实际应用...相关推荐

  1. 揭开均线系统的神秘面纱_在应用程式审查API中揭开新玩法的神秘面纱

    揭开均线系统的神秘面纱 During the #11WeeksOfAndroid the new Play In-App Review API was announced. This was a lo ...

  2. 【Paper】2014_多智能体系统一致性问题研究_唐骥宇

    原文地址:[1]唐骥宇. 多智能体系统一致性问题研究[D].长安大学,2014. 2014_多智能体系统一致性问题研究_唐骥宇

  3. matlab用lism求零输入响应,信号与系统matlab课后作业_北京交通大学讲解.docx

    信号与系统matlab课后作业_北京交通大学讲解.docx 信号与系统MATLAB平时作业 学院 电子信息工程学院 班级 姓名 学号 教师 钱满义 MATLAB习题 M3-1 一个连续时间LTI系统满 ...

  4. 自适应均线系统 python_Kaufman的自适应移动平均线(AMA)

    技术分析往往离不开均线系统,她是我们观察价格走势的基础. 短期均线贴近价格走势,灵敏度高,但会有很多噪声,产生虚假信号:长期均线在判断趋势上一般比较准确 ,但是长期均线有着严重滞后的问题.我们想得到这 ...

  5. 最佳均线系统操作依据

    最佳均线系统操作依据 短线规则: 1.低位放量上涨突破20日均线,缩量回跌调整到20日均线时为买入点. 2.远离20日均线20-30%为获利了结点. 3.买股需要在120日线上. 4.20日线上穿24 ...

  6. 均线系统之详解 —— 第一讲

    均线-我们主要的指标 任何股票软件安装后,我们首先看到的就是K线与均线组合的主图.可见,均线系统是多么的普遍和实用.但真正用好均线系统的有多少呢?为什么我们总是到处寻找更好的指标?总是觉得还有更容易, ...

  7. 新手村 - 第三站,认识均线系统

    大家好呀,我是你们的胖企鹅,上一篇已经介绍了怎么看 K线,今天就来说说,股票中均线系统. 还是老样子,给大家先来个总结: 所谓的均线就是不同阶段的平均值画出的点链接在一起成线 常说的均线系统,是N日前 ...

  8. [量化-012]缠论之五--均线系统

    均线,五日均线,十日均线,三十日均线,六十日均线. 均线之间的穿插关系,表示走势的强弱. 重大行情的变化,通常跟两条均线的反复纠缠行走相关.当两条均线反复纠缠的时候,表明趋势要反转,下跌趋势变成上涨趋 ...

  9. 循序渐进:用python做金融量化分析(四)双均线系统策略

    上一节中讲了单均线系统最优参数的寻找,这一节我们开讲双均线系统,在编程设计上,双均线系统相对于单均线系统来说多了一个均线循环,在短期均线循环里面再嵌套一个长期均线循环,其它方面和单均线系统变化不大,由 ...

最新文章

  1. linq TO XML 基础
  2. Deep Residual Learning for Image Recognition(MSRA-深度残差学习)
  3. MSDN宇宙版到货!
  4. javaWeb:相关监听方法汇总
  5. 服务器安装 accessdatabaseengine_.net IIS 服务器环境配置
  6. IDEA2019.3 双击启动无反应解决方法
  7. 一篇文章搞懂数据仓库:元数据分类、元数据管理
  8. android 游戏摇杆ui,LayaBox实现2D游戏八方向虚拟摇杆
  9. 2019-1-3 每日一记
  10. Excel表格数据如何批量乘以一个数字
  11. 涉密计算机设备保密管理系统,保密室设备——涉密计算机及移动存储介质保密管理系统(三合一)...
  12. contextcapture多区块点云_Smart 3D (ContextCapture) 4.4.6版本最新功能
  13. 计算机网络保密承诺书,保密承诺书集合5篇
  14. [附源码]计算机毕业设计JAVA 停车场管理系统
  15. win10系统无法连接远程服务器,笔者修复win10系统无法连接远程服务器的图文教程...
  16. 视觉slam14讲学习(一)之se3上的定位表示:轨迹显示与轨迹误差
  17. 程序员的高薪还能持续吗?
  18. RabbitMQ 延迟队列详解
  19. 学术期刊划分(教你认识SCI、EI、SSCI、IEEE、CSSCI...)
  20. Token的基本介绍

热门文章

  1. signature=988b478f2af5e3a20272ed9c171b1a97,Problems of Conquering Everest
  2. 计算机专业学习的32个网站
  3. Linux基本操作命令(未完待续)
  4. 今天是我第一次开通本博客 自己爱好学习破解软件,OEM软件。易语言做软件等等,
  5. python开发视频播放器_python_十几行代码实现简单播放器
  6. PC端——如何屏蔽掉某网站-极度简洁-继hosts后的全新改良版~!
  7. flink worldcount
  8. 计算机培训总结ppt用什么音乐,音乐教育行业年终总结ppt
  9. 解决Chrome浏览器中无法通过代码实现自动播放错误
  10. luajit开发文档中文版(二)LuaJIT扩展