依稀记得自己在大三时期的一门课程设计,自告奋勇的要求做了一个仿元气骑士的游戏——西游之下(当时沉迷于传说之下,起了这么一个中二的名字。。。)
当时做完之后,觉得自己也没谁了,吊打一切那种。然后给老师看后,老师却说我的项目是抄的,为此还和好友还跟老师一起对峙了一番。
不过后期编程能力稍有起色之后再回头看当时的项目,真的是不堪入目。所谓零内聚,全耦合说的就是我当时的代码吧。。。。。。
后来,大四时期我到了一家游戏公司有了为期三个月的实习经历,虽然说核心技术没学到什么,每天就是拼一拼UI,加一加控件什么的,但是我算是第一次真正接触到了商业级代码,给当时弱小的自己带来了巨大的冲击,原来把代码写的如此规矩规整是如此爽的一件事情。所以当时我有一个非常喜欢做的一件事情,就是每天扒公司的源码看,再加上当时的老大嫌弃我们的编码水平,一本《图解设计模式》彻底让我对编程的认识得到提升。
说了这么多,正式开始。首先贴上StrangeIOC教程的官方链接http://strangeioc.github.io/strangeioc/TheBigStrangeHowTo.html#h.3e40286vrfxn
因为个人能力所限,目前自然还是要从官方教程说起,同时再加上一些小小的个人见解,如有问题,还请各位指出批评。
简介
StrangeIOC从字面上看,就可以知道是一种使用控制反转的框架,用过大名鼎鼎Spring框架的对这一概念自然非常熟悉,其中他主要包括:
- 核心绑定框架
- 依赖注入
- 两种不同的事件总线:
一种为事件调度
一种为信号调度(官方首推这种方式) - MonoBehaviour类的调解(从而可以将UnityEngine提供的参数更好的划分出来处理)
- 可选的MVCS(模型/视图/控制器/服务)结构
- 多个上下文环境
- 高度可拓展内容
接着就用官方的案例进行解释,由于官方首推信号调度方式,因此这里使用官方的信号案例。
框架入口
首先我们先来看一张官方的结构图
按照这张图,我们寻找到案例的框架入口类SignalsRoot类,该类继承ContextView类。在入口类中,我们Unity的Awake()生命周期中,创建框架环境SignalsContext类。
在创建环境时,首先将原事件调度解绑,重新绑定为信号绑定。
protected override void addCoreComponents()
{
base.addCoreComponents();
injectionBinder.Unbind();
injectionBinder.Bind().To().ToSingleton();
}
创建一个Start信号,并在之后覆盖环境启动方法时触发Start信号。override public IContext Start()
{
base.Start();
StartSignal startSignal= (StartSignal)injectionBinder.GetInstance();
startSignal.Dispatch();
return this;
}
剩下的就是重写mapBindings方法,并在其中对所需注入进行绑定。
注意启动信号需要设置成为单次启动模式。commandBinder.Bind().To().Once ();
绑定
在控制反转的框架中,最重要的部分自然就是绑定,下面为几种不同方式的绑定方法。1. Bind().To();
2. Bind(typeof(IRoundLogic)).To(typeof(RoundLogic));
3. IBinding binding = Bind(); //使用IBinding 的时候需要引用strange.framework.api;
4. Bind().To().ToName(“Logic”); //使用名称bangding绑定
做好了这些,一个框架最基础的部分就完成了,也就是图中的①②部分。
在绑定时有几大绑定对象:
- injectionBinder:用于绑定实体模型类,使用接口绑定。
- mediationBinder:用于绑定视图与视图调制器,视图需继承View,调制器继承Mediator
- commandBinder:用于绑定命令
对于一些正常的逻辑触发信号,则可以将其设置为单例模式,这样命令和调制器都可以获取到它。
注入
注入时,首先一定要将要注入参数设置为属性,并根据不同情况在其属性注解中予以标识。1.[Inject]//常规注入
public ExampleView view{ get; set;}
2.[Inject(ContextKeys.CONTEXT_VIEW)]//系统中提供的全局属性或自己命名
public GameObject contextView{get;set;}
信号调度
信号调度相比起事件调度最大的优点就是在于安全,当消息与回调不匹配时会断开执行,同时分发结果不再创建实例,因此也不需要GC回收更多的垃圾。
自己扩展信号时,可以添加参数限定,即可用此方法限制参数public class ScoreChangedSignal : Signal<string> { }
信号使用事件委托的方式,因此可以在上面绑定方法,最后使用Dispatch方法进行信号触发。