因为是有关Command和Service的事件,所以将事件枚举命名为
public enum SMCubeEvent { GetPositionComplete }
先看Service层吧
//接口 using strange.extensions.dispatcher.eventdispatcher.api; public interface IPositionServise { [Inject] IEventDispatcher dispatcher { get; set; } void GetPosition(); }
//实现 using strange.extensions.context.api; using strange.extensions.dispatcher.eventdispatcher.api; public class LinePositionServise : IPositionServise { [Inject] public CubePositionModel DataModel { get; set; } [Inject]//局部的分发器 public IEventDispatcher dispatcher { get; set; } public void GetPosition() { //假装是远程获取的数据 Vector3 pos = new Vector3(Random.Range(0, 2), Random.Range(0, 2), Random.Range(0, 2)); //保存数据到Model DataModel.pos = pos; //获取到后通知Command层回调 dispatcher.Dispatch(SMCubeEvent.GetPositionComplete,pos); } }
然后是Command层
using strange.extensions.command.impl; using strange.extensions.dispatcher.eventdispatcher.api; public class CubeInitCommand : EventCommand { [Inject]//注入服务层,用来调用事先准备好的接口 public IPositionServise PositionServise { get; set; } public override void Execute () { Retain();//保持Command不被销毁,因为服务层获取数据一般都不是立刻的 PositionServise.dispatcher.AddListener(SMCubeEvent.GetPositionComplete, OnComplete); //通过服务层获取数据 PositionServise.GetPosition(); } private void OnComplete(IEvent evt) { dispatcher.RemoveListener(SMCubeEvent.GetPositionComplete, OnComplete); //发送命令给Mediator,初始化位置 dispatcher.Dispatch(MCCubeEvent.InitPositionComplete, (Vector3)evt.data); Release();//释放掉,放置内存泄漏 } }
总结:这个的交互和View-Mediator有点相像。在Command中获得Service的注入,直接调用接口来交互它,Command中通过注入的Service的局部dispatcher来监听它请求数据的完成回调,当Service层发出相应的请求完成事件,Command中的回调自然被触发。不同的是,因为Service层一般是用来和网络交互的,也就是说它提供的接口是有延迟性的,而Command是完成就会被销毁的,所以要用Retain()来保持Coammand不被销毁,事件完成后在手动销毁Release()。
因为是有关Mediator和Command的事件,所以将事件枚举命名为
public enum MCCubeEvent { UpdateCunePos, UpdateCunePosComplete }
先是Mediator层
using UnityEngine; using strange.extensions.mediation.impl; using strange.extensions.dispatcher.eventdispatcher.api; using strange.extensions.context.api; public class CubeViewMediator : EventMediator { [Inject] public CubeView cubeView{ get; set;} public override void OnRegister () { //监听Command处理完成的回调 dispatcher.AddListener(MCCubeEvent.UpdateCunePosComplete, OnUpdatePosComplete); cubeView.dispatcher.AddListener(VMCubeEvent.UpdatePosition, OnUpdatePos); } public override void OnRemove () { cubeView.dispatcher.RemoveListener(VMCubeEvent.UpdatePosition, OnUpdatePos); dispatcher.RemoveListener(MCCubeEvent.UpdateCunePosComplete, OnUpdatePosComplete); } private void OnUpdatePos(IEvent evt) { //发送命令给Commamd,事先会在Context下绑定,直接调用Command的Execute()方法 dispatcher.Dispatch(MCCubeEvent.UpdateCunePos,(int)evt.data); } private void OnUpdatePosComplete(IEvent evt) { cubeView.UpdatePosition((Vector3)evt.data); } }
然后是Command层
using UnityEngine; using strange.extensions.command.impl; public class CubeUpdateCommand : EventCommand { [Inject] public CubePositionModel DataModel { get; set; } public override void Execute() { Vector3 newPos = DataModel.pos; newPos.x += Random.Range(-2f, 2f); DataModel.pos = newPos; //处理完后,回调给Mediator,Mediator事先已经监听好了 dispatcher.Dispatch(MCCubeEvent.UpdateCunePosComplete,newPos); } }
下面是绑定
commandBinder.Bind(MCCubeEvent.UpdateCunePos).To<CubeUpdateCommand>();
总结:两者都是通过全局的dispatcher发送事件的。Mediator通过发送事先在绑定处绑定好了命令的事件来通知Command处理,Command通过发送Mediator层事先绑定好的回调事件来通知Mediator。
因为是View和Mediator的交互,所以我将事件枚举命名为
public enum VMCubeEvent { UpdatePosition, }
新建CubeView
using UnityEngine; using strange.extensions.mediation.impl; using strange.extensions.dispatcher.eventdispatcher.api; public class CubeView : View { [Inject]//使用局部的派发器 public IEventDispatcher dispatcher { get; set; } //提供接口 public void UpdatePosition(Vector3 pos){ this.transform.position = pos; } private void OnMouseDown() { //Cube被点击后,发送命令通知Mediator dispatcher.Dispatch(VMCubeEvent.UpdatePosition,Random.Range(1,10)); } }
对应的Mediator
using UnityEngine; using strange.extensions.mediation.impl; using strange.extensions.dispatcher.eventdispatcher.api; using strange.extensions.context.api; public class CubeViewMediator : EventMediator { [Inject]//注入View,直接调用View接口交互 public CubeView cubeView{ get; set;} public override void OnRegister () { //监听View层发出的命令 cubeView.dispatcher.AddListener(VMCubeEvent.UpdatePosition, OnUpdatePos); } public override void OnRemove () { cubeView.dispatcher.RemoveListener(VMCubeEvent.UpdatePosition, OnUpdatePos); } private void OnUpdatePos(IEvent evt) { //发送命令去Command层做逻辑计算等 //evt.data View传过来的数据 //当命令有回应时,直接调用View接口传递给View //cubeView.UpdatePosition((Vector3)evt.data); } }
总结:View用来和用户交互,感知事件的发生,然后通过局部的dispatcher派发命令通知Mediator层,Mediator事先通过这个局部的dispatcher监听好事件的回调,触发这个回调(处理),处理完成后,通过View引用直接访问提供好的接口更新交互。
1.创建空物体Root,创建RootContextView挂载上去,用来实例化Context。
//RootContextView.cs文件 using strange.extensions.context.impl; using UnityEngine; public class RootContextView : ContextView { void Awake() { //创建Context this.context = new DemoContext (this); } }
2.创建DemoContext类,用来绑定
using UnityEngine; using strange.extensions.context.impl;//MVCSContext using strange.extensions.context.api;//ContextEvent.START public class DemoContext : MVCSContext { public DemoContext(MonoBehaviour view):base(view){} protected override void mapBindings () { //Binding Todo //绑定启动命令,此方法完成后,就会自动分发ContextEvent.START命令 commandBinder.Bind (ContextEvent.START).To<StartCommand> ().Once(); } }
3.创建StartCommand类,作为启动命令。
using UnityEngine; using strange.extensions.command.impl; public class StartCommand : Command { public override void Execute () { Debug.Log ("Hello World!"); } }
4.解说一下,创建RootContextView继承自ContextView(MonoBehaviour的子类),挂载到场景中,自动实例化调用Awake()方法,实例化DemoContext类,DemoContext类继承自MVCSContext,里面重写了mapBindings()方法在Context创建时自动调用,用于绑定关系,最后绑定启动命令到StartCommand,在绑定结束后就会调用这个事件,调用StartCommand的Execute()方法,游戏的起点。
StrangeIoc是一个基于MVCS的小型框架。M指的是模型,用于访问数据层,保存取出来的数据等。V指的是视图,就是我们看到的东西,一般会以组件的形式挂载到GameObject上。C指的是Controller,利用命令Command负责和Service、Model、Mediator的交互。S指的是服务层,用户与存储服务器交互,请求、更新、保存数据。
Root继承自contextView用来当做足见挂载到物体上,主要作用来实例化Context。
Context用来绑定各个层次东西的关系等,绑定一个叫ContextEvent.START的命令,自动触发,这是开始。
View挂在了物体上,会自动实例化,实例化后会自动创建Mediator中间层并调用OnRegister()方法,发送命令请求S或M获取初始化数据,绑定一些监听等,如数据更新等。
S层会将数据保存到M层。
M和S接受到命令,取出数据后,在发送命令回Mediator中间层。