类比Spring框架来实现OC中的依赖注入
如果你之前使用过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中的依赖注入的更多相关文章
- Spring-初识Spring框架-IOC控制反转(DI依赖注入)
---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...
- JavaEE开发之Spring中的依赖注入与AOP
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- Spring学习(一)——Spring中的依赖注入简介【转】
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- Spring学习(一)——Spring中的依赖注入简介
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
- 三大框架 之 Spring(IOC控制反转、DI依赖注入)
目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...
- Spring学习(三)——Spring中的依赖注入的方式
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
- C#中的依赖注入那些事儿
目录 目录 1 IGame游戏公司的故事 1.1 讨论会 1.2 实习生小李的实现方法 1.3 架构师的建议 1.4 小李的小结 2 探究依赖注入 2.1 故事的启迪 2.2 正式定义依赖注入 3 依 ...
- React 源码中的依赖注入方法
一.前言 依赖注入(Dependency Injection)这个概念的兴起已经有很长时间了,把这个概念融入到框架中达到出神入化境地的,非Spring莫属.然而在前端领域,似乎很少会提到这个概念,难道 ...
随机推荐
- 上传文件到linux服务器
可以在SecureCRT下上传 先用使用命令下载一个文件:yum install lrzsz -y 然后在跳转到要保存的目录 最后,拖拽文件到secureCRT中即可
- PHP 递归实现层级树状展现数据
<?php $db = mysql_connect('localhost', 'root', 'root') or die('Can\'t connect to database'); mysq ...
- jquery 编写插件入门
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <sc ...
- 【HDU 5808】 Price List Strike Back (整体二分+动态规划)
Price List Strike Back There are nn shops numbered with successive integers from 11 to nn in Bytelan ...
- iOS 登陆之使用ShareSDK
0. 概述 登陆要使用ShareSDK,可以实现多社交平台账号登陆,短信验证,并且都是永久免费的. 网址:www.mob.com 1.iOS 登陆之界面设置
- SVG的a链接
SVG的a链接: <%@ page language="java" contentType="text/html; charset=UTF-8" page ...
- HTML 颜色值
HTML 颜色值 颜色由红(R).绿(G).蓝(B)组成. 颜色值 颜色值由十六进制来表示红.绿.蓝(RGB). 每个颜色的最低值为0(十六进制为00),最高值为255(十六进制为FF). 十六进制值 ...
- 使用AIR进行移动APP开发常见功能和问题(下)
1. Air如何判断android.ios 平台网络连接状态? Android,使用as3原生api: if(NetworkInfo.isSupported)//只有android支持 Networ ...
- Hadoop-2.x启动HDFS和YARN的方式
逐一启动(实际生产环境中的启动方式) * sbin/hadoop-daemon.sh start|stop namenode|datanode|journalnode * sbin/yarn-daem ...
- oracle_decode、case
Case具有两种格式.简单Case函数和Case搜索函数. --简单Case函数 CASE sex WHEN '1' THEN '男' WHEN '2' THEN '女' ELSE '其他' END ...