如果你之前使用过JavaEE开发中的Spring框架的话,那么你一定对依赖注入并不陌生。依赖注入(DI: Dependency Injection)是控制反转(IoC: Inversion of Control)的实现方式之一,另外一种是依赖查找(DL: Dependency Lookup)。当然在Spring框架中主要使用到了控制反转中的依赖注入这种方式。当然在Spring框架中除了依赖注入外,还有一个重要的概念那就是面向切面编程(AOP)。

简单的说,依赖注入负责往类中注入依赖对象,而面向切面编程则负责往里添加代码段的。本篇博客我们主要聊的就是依赖注入,关于AOP和依赖查找的内容,如果以后有机会,会在后边的博客进行介绍。

本篇博客不是使用Java语言实现的,而是使用Objective-C来实现的。实现依赖注入的具体方式就是使用反射机制来实现的,本篇博客,我们就使用OC的反射机制来看一下iOS开发中的依赖注入的实现方式。当然在Java的Spring框架中是在XML文件中配置的JavaBean,入乡随俗,本篇博客我们就使用iOS开发中常用的PList文件来存储类似于JavaBean的东西,也就是数本篇博客我们使用PList文件来代替XML文件。废话少说,进入我们的主题。

一、依赖注入的实现机制

依赖注入,听起来特别高大上,其实真正理解其工作原理后,也没什么东西。本篇博客采用的代码实例与之前我们聊“策略模式”的示例一致。关于之前的策略模式的博客,请移步于《“穿越火线”中的“策略模式”(Strategy Pattern)》。当然我们之前的示例是使用的Swift来实现的,本篇博客使用的是OC, 虽然语言不通,但是思想是一致的。在“策略模式”中我们通过策略模式为不通的军官提供不同的武器策略。而本篇博客,我们依然采用这个思路,不过我们是依照“依赖注入”的方式来为不同的军官提供不同的武器策略。

下方就是我们本篇博客使用示例的类图。WeaponType是所有武器的父类,在其中扮演者“武器接口”的角色。所有的武器都继承自WeaponType。而Character角色类依赖于WeaponType武器接口类,所有Character与WeaponType存在依赖关系。

  

“依赖注入”从字面上看,就是注入依赖。也就是将依赖关系的对象注入到相应的类中。而在上述示例中,Character依赖于WeaponType接口,如果使用“依赖注入”来解决这层依赖关系的话,就是通过反射机制(“Runtime”)动态的将WeaponType的子类的对象注入到Character对应的依赖属性中去。而反射时需要的依赖关系信息,我们就从PList文件中进行读取,当然Java中是从XML中进行配置的,这就是“依赖注入”。

本篇博客我们就来根据上述类图的依赖关系,来完整的实现这个实例。当然在真正实现时,我们用到的主要核心内容是“面向接口编程”、“面向对象的多态性”、“反射机制”、“PList文件的读取与操作”。下方会一一介绍。

二、示例工程的目录结构

接下来我们就来概述一下本篇博客所使用到的实例的工程结构,也就是先整体的了解一下本篇博客所涉及的示例工程。下方这个工程目录结构就是我们本篇博客所涉及的示例的目录结构。Weapon文件夹中存放的就是武器策略所涉及的武器接口与武器类。Character文件夹中存放的就是武器使用者所对应的目录。PList文件则存储的是Character类依赖WeaponType接口的具体类的依赖信息。Relation类则是负责读取PList文件中的依赖信息,根据这些依赖信息将依赖对象通过“反射机制”注入到相应的类中。

  

三、PList文件中的内容

本篇博客中的PList文件的作用就类似于Spring框架中用来配置JavaBean的XML。当然我们本篇博客的PList文件的存储内容的结构与形式与Spring中的XML有所不同,但是其作用都是一样的,都是用来描述类之间的依赖关系的。

下方截图就是本篇示例所涉及的PList文件中的内容。从下方文件中,我们可以看出其中存储了三个类的信息,一个是Lieutenant(中尉)类,一个是Captain(上尉)类,最后一个就是Soldier(士兵)类。每个类也就是Java中常说的JavaBean,Relation类可以根据反射机制根据这些类在PList文件中提供的信息来实例化相应的类的对象。

我们就以Lieutenant为例。在PList文件中,其实Lieutenant就对应这一个类,从Lieutenant对应的信息来看,Lieutenant的对象由Character类实例化,但是在实例化时需要给Character的对象依赖属性weapon赋一个HK48Weapon类的对象。当然这一系列实例化以及赋值的动作都是由反射机制完成。稍后我们会给出具体实现。

  

四、通过PList文件创建类

Relation类就是赋值加载相应的PList文件内容,然后根据其加载的内容利用反射机制生成相应的类的对象。下方代码片段就是Relation类加载上述的PList文件内容,让后给据这些内容生成相应的类的对象的。下方这个代码片段根据Relation提供的上下文分别创建了Lieutenant对象、Captain对象以及Soldier的对象。具体如下所示。

  

根据上下文创建完对象后,都会调用fire方法,因为每个对象对应的上下文不同,也就是注入的依赖对象不同,所以fire方法执行的结果也不同。下方是上述代码的运行结果,如下所示:

  

五、使用反射机制注入依赖对象

接下来我们就要来看一下如何使用反射机制来注入依赖对象的,也就是Relation类的具体实现。

1.通过初始化方法提供plist文件

下方是Relation类的构造器,构造器中有个参数plistFileName, 该参数就是用来存储依赖上下文信息的plist文件。Relation类在实例化对象时,收到该文件后,会加载该文件中的上下文信息,也就是我们plist文件中的内容。具体代码如下所示。

  

下方代码片段就是本篇博客的核心代码,根据PList文件中提供的上下文信息,生成相应的对象,并给对象相应的属性注入依赖对象。当然下方是通过Setter方法来设置依赖对象的。设置完毕后,返回该注入好依赖的对象。具体如下所示。

  

今天博客就先到这儿吧,以后我们找个合适的时间再聊聊依赖查找和面向切面编程的东西。下方的github链接是本篇博客所涉及Demo的源码分享链接,如下所示。

源码的github分享链接:https://github.com/lizelu/DependencyInjectionForiOS

类比Spring框架来实现OC中的依赖注入的更多相关文章

  1. Spring-初识Spring框架-IOC控制反转(DI依赖注入)

    ---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...

  2. JavaEE开发之Spring中的依赖注入与AOP

    上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...

  3. JavaEE开发之Spring中的依赖注入与AOP编程

    上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...

  4. Spring学习(一)——Spring中的依赖注入简介【转】

      [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...

  5. Spring学习(一)——Spring中的依赖注入简介

    [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...

  6. 三大框架 之 Spring(IOC控制反转、DI依赖注入)

    目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...

  7. Spring学习(三)——Spring中的依赖注入的方式

    [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...

  8. C#中的依赖注入那些事儿

    目录 目录 1 IGame游戏公司的故事 1.1 讨论会 1.2 实习生小李的实现方法 1.3 架构师的建议 1.4 小李的小结 2 探究依赖注入 2.1 故事的启迪 2.2 正式定义依赖注入 3 依 ...

  9. React 源码中的依赖注入方法

    一.前言 依赖注入(Dependency Injection)这个概念的兴起已经有很长时间了,把这个概念融入到框架中达到出神入化境地的,非Spring莫属.然而在前端领域,似乎很少会提到这个概念,难道 ...

随机推荐

  1. redis php sort 函数

    很多人把redis当成一种数据库,其实是利用redis来构造数据库的模型,有那种数据库的味道.但是在怎么构建还是key和value的关系.根真正的关系型数据库还是不一样的.效率高,不方便:方便的,效率 ...

  2. @pathvariable 注解

    1.4. @PathVariable 注解 带占位符的 URL 是 Spring3.0 新增的功能,该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义 通过 @PathVar ...

  3. 位运算,算术、逻辑运算详解-java篇

    /** * 功能: * 位运算符,原码.反码.补码规则: * 1.二进制的最高位是符号位:0表示正数,1表示负数 * 2.正数的原码.反码.补码都一样 * 3.负数的反码=它的原码符号位不变,其他位取 ...

  4. AJAX 跨域请求的解决办法:使用 JSONP获取JSON数据

    由于受到浏览器的限制,ajax不允许跨域通信.如果尝试从不同的域请求数据,会出现安全错误.如果能控制数据驻留的远程服务器并且每个请求都前往同一域,就可以避免这些安全错误.但是,如果仅停留在自己的服务器 ...

  5. NodeMCU之旅(一):构建、刷入固件,上传代码

    扬帆起航 本系列文章将试图实现,使用Web页面远程点亮led.具体包括: 在NodeMCU上搭建HTTP服务器,使其可以通过Web页面配置要接入的网络. 在配置页面可以显示附近中英网络名与信号强度. ...

  6. MySQL只恢复某个库或某张表

    在Mysqldump官方工具中,如何只恢复某个库呢? 全库备份 [root@HE1 ~]#mysqldump -uroot -p --single-transaction -A --master-da ...

  7. HDU-1995-汉诺塔V

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1995 这题不知道该说水还是不水,对于这题我看到题目数据,就有了想法,因为题目数据给的好 所以我直接 假 ...

  8. Canvas translate- 平移

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 《转》VS2010进行远程调试方法总结

    ---恢复内容开始--- 原文地址:http://blog.sina.com.cn/s/blog_a459dcf5010153o7.html 假设现在有A.B两台PC机. VS2010安装在A机器上, ...

  10. ubuntu无法进入桌面的修复

    今天的kubuntu更新后停在了启动logo上,无法进入系统界面了. 先在网上找了找,搜到了一个看起来很像的. 1)ubuntu在系统启动logo过后无法进入桌面的处理方法 一般情况下,无法显示桌面, ...