类比Spring框架来实现OC中的依赖注入

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

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

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

 

1、依赖注入的实现机制编程

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

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

  

 

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

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

 

 

2、示例工程的目录结构3d

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

  

 

 

3、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类的对象。固然这一系列实例化以及赋值的动做都是由反射机制完成。稍后咱们会给出具体实现。

  

 

 

4、经过PList文件建立类

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

  

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

  

 

 

 

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

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

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

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

  

 

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

  

 

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

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

相关文章
相关标签/搜索