基于StrangeIoC的点击方块加分的Demo

 

1、项目简介:

创建一个Cube,Cube上有一个Text的UI显示一个随机的分数,Text上的值也是随机的,当我们鼠标点击中一次Cube分数就会增加一。

运行逻辑是:开始的时候View通过Mediator向Controller请求数据,然后Controller向服务端请求数据,服务端Service返回一个随机值给Controller里面创建的请求数据的Command,Controller逻辑层再将数据传递给Mediator,Mediator再负责显示到View上,然后为了将数据保存下来Controller再将数据传给Models模型层。然后我们再创建一个点击更新数据的Command,在这个Command里面我们将模型层的数据加一,然后再将数据返回给Services.
首先我们的代码有这些,我们分为Command层Model层,Service层,View层,就是MVCS,Command负责传递命名,Model负责保存数据,Service负责与服务器交互,View负责视图的显示,所有的代码架构如下:

 

2、实现步骤:

(1)首先创建ContextView开启整个框架,

public class Demo1ContextView : ContextView
{
    private void Awake()
    {
        this.context = new Demo1Cntext(this, true);
        context.Start();
    }
}

(2)然后创建MVCSContext负责绑定各个事件:

public class Demo1Cntext : MVCSContext
{

    public Demo1Cntext(MonoBehaviour View, bool autoStartup) : base(View, autoStartup) { }

    protected override void mapBindings()//进行绑定映射
    {
        //model    M
        injectionBinder.Bind<ScoreModel>().To<ScoreModel>().ToSingleton();
        injectionBinder.Bind<AudioManager>().To<AudioManager>().ToSingleton();

        //service   S
        injectionBinder.Bind<IScoreService>().To<ScoreService>().ToSingleton();//ToSingleton表示这个对象只会在整个工程中生成一个

        //command    C
        commandBinder.Bind(Demo1CommandEvent.RequestScore).To<RequestscoreCommand>();
        commandBinder.Bind(Demo1CommandEvent.UpdateScore).To<UpdateScoreCommand>();

        //mediator   V
        mediationBinder.Bind<CubeView>().To<CubeMediator>();//完成View和mediator的绑定


        //绑定开始事件  一个StartCommand  这个StartCommand会立即调用
        commandBinder.Bind(ContextEvent.START).To<StartCommand>().Once();//把哪个事件与自己的StartCommand绑定上
    }
}

 

(3)首先是开始命令:

using strange.extensions.command.impl;
using UnityEngine;

public class StartCommand : Command
{
    [Inject]
    public AudioManager audioManager { get; set; }
    public override void Execute()
    {

        audioManager.Init();

        Debug.Log("StartCommand!");
    }
}

 

(4)接下来是视图层的脚本显示UI部分:

public class CubeView : View
{

    [Inject]
    public IEventDispatcher dispacher { get; set; }

    private Text scoreText;

    /// <summary>
    /// 做初始化
    /// </summary>
    public void Init()
    {
        scoreText = transform.Find("Canvas/ScoreText").GetComponent<Text>();
    }

    [Inject]
    public AudioManager audioManager { get; set; }
    private void OnMouseDown()
    {
        //加分
        Debug.Log("OnMouDown");
        audioManager.playAudio("explosive");

        dispacher.Dispatch(Demo1MediatorEvent.ClickDown);
    }
    public void Updatescore(int score)
    {
        scoreText.text = score.ToString();
    }
}

 

(5)接下来是视图层通过View层Mediator向Command发起分数的请求:

public class CubeMediator : Mediator
{

    [Inject]//可以访问到与自身绑定的 CubeView  完成注入的意思
    public CubeView cubeView { get; set; }

    [Inject(ContextKeys.CONTEXT_DISPATCHER)]//表示全局的派发器
    public IEventDispatcher dispatcher { get; set; }

    public override void OnRegister()//注册  当属性都调用完成后就会去调用这个方法  在OnRegister里面可以访问这些属性
    {
        cubeView.Init();

        dispatcher.AddListener(Demo1MediatorEvent.ScoreChange, OnScoreChange);//监听注册方法返回分数
        cubeView.dispacher.AddListener(Demo1MediatorEvent.ClickDown, OnClickDown);

        //通过dispatcher发起请求分数的命令
        dispatcher.Dispatch(Demo1CommandEvent.RequestScore);

        base.OnRegister();
    }
    public override void OnRemove()//当取消运行的时候会调用这个   当Mediator对应的View的视图被销毁的时候会调用OnRemove
    {
        dispatcher.RemoveListener(Demo1MediatorEvent.ScoreChange, OnScoreChange);//移除监听
        cubeView.dispacher.RemoveListener(Demo1MediatorEvent.ClickDown, OnClickDown);
    }
    //将返回的分数传递给View层
    public void OnScoreChange(IEvent evt)
    {
        cubeView.Updatescore((int)evt.data);
    }

    //加分
    public void OnClickDown()
    {
        dispatcher.Dispatch(Demo1CommandEvent.UpdateScore);
    }
}

 

(6)下面是几个发起请求需要的枚举值,有CommandEvent、ServiceEvent、MediatorEvent:

public enum Demo1CommandEvent
{
    RequestScore,
    UpdateScore
}

public enum Demo1MediatorEvent
{
    ScoreChange,
    ClickDown
}

public enum Demo1ServiceEvent
{
    RequestScore
}

 

(7)接下来就是Command层了,有请求分数和更新分数的命令,所以两个Command:

public class RequestscoreCommand : EventCommand 
{

    [Inject]
    public IScoreService scoreService { get; set; }
    [Inject]
    public ScoreModel scoreModel { get; set; }

    public override void Execute()//表示命名执行的时候
    {
        Retain();//表示让这个请求先不销毁,等接收到数据后进行释放
        //添加监听器,监听OnComplete方法,第一个参数表示方法的事件枚举类型, 第二个参数表示一个方法
        scoreService.dispatcher.AddListener(Demo1ServiceEvent.RequestScore, OnComplete);

        scoreService.RequestScore("http://xx/xx/xxx");
    }

    //这个方法表示当scoreService请求分数完成后就会调用这个方法去取得数据
    private void OnComplete(IEvent evt) {//IEvent存储的就是参数

        Debug.Log("request score complete"+evt.data);
        scoreService.dispatcher.RemoveListener(Demo1ServiceEvent.RequestScore, OnComplete);//移除对OnComplete的监听
        scoreModel.score = (int)evt.data;
        dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, evt.data);

        Release();//释放请求,销毁当前对象
    }
}

public class UpdateScoreCommand : EventCommand
{
    [Inject]
    public ScoreModel ScoreModel { get; set; }
    [Inject]
    public IScoreService scoreServer { get; set; }

    public override void Execute()
    {
        ScoreModel.score++;
        scoreServer.UpdateScore("http://xx/xx", ScoreModel.score);

        dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, ScoreModel.score);
    }

}

 

(8)然后就是Servicevice层了,一个是接口,一个是实现接口的类

public interface IScoreService  
{

    void RequestScore(string url);//请求分数

    void  OnReceiveScore();//收到服务器端发送的分数

    void UpdateScore(string url, int Score);//更新分数

    IEventDispatcher dispatcher { get; set; }
}
 

public class ScoreService : IScoreService
{

    [Inject]
    public IEventDispatcher dispatcher { get; set; }


    public void RequestScore(string url)请求分数
    {
        Debug.Log("Request Score from url:" + url);
        OnReceiveScore();
    }

    public void  OnReceiveScore()收到服务器端发送的分数
    {
        int score = Random.Range(0, 100);
        dispatcher.Dispatch(Demo1ServiceEvent.RequestScore, score);//通过Demo1CommandEvent.RequeestScore这个事件将数据发送出去
    }

    public void UpdateScore(string url, int Score)//更新分数
    {
        Debug.Log("Update score to url:"+url+"new score:"+Score);
    }
}
 

(9)最后就是模型层,保存分分数,数据:

public class ScoreModel
{
    public int score { get; set; }
}


(10)至于AudioManager在这里只用于音乐播放

(11)这样就完成了,开始请求获取一个初始分数,往后每点击Cube一次数据就会更新一次数据+1。

(12)运行结果为:

点击运行时:

鼠标点击方块上时:

 

3、总结:

(1)理清项目的流程:

当程序刚运行起来的时候,由于我们调用了ContextView的context.Start函数,而在Context中将ContextEvent.START事件与StartCommand绑定了起来,所以调用StartCommand的Execute函数执行如下代码:

audioManager.Init();//加载音效文件

Debug.Log("StartCommand!");

故控制台会打印出StartCommand!

 

随后,在将CubeView与CubeViewMediator进行绑定的时候,调用CubeViewMediator的Register函数,其中有这样几句代码:

dispatcher.AddListener(Demo1MediatorEvent.ScoreChange, OnScoreChange);//监听注册方法返回分数
cubeView.dispacher.AddListener(Demo1MediatorEvent.ClickDown, OnClickDown);

//通过dispatcher发起请求分数的命令
dispatcher.Dispatch(Demo1CommandEvent.RequestScore); 

在执行到dispatcher.Dispatch(Demo1CommandEvent.RequestScore); 的时候会调用RequestscoreCommand的Execute方法:

scoreService.dispatcher.AddListener(Demo1ServiceEvent.RequestScore, OnComplete);

scoreService.RequestScore("http://xx/xx/xxx");

在执行上述的第一句代码时,意思是当有Demo1ServiceEvent.RequestScore发生时,调用OnComplete函数

在执行第二句代码时:

调用ScoreService类中的方法:

public void RequestScore(string url)请求分数
{
        Debug.Log("Request Score from url:" + url);
        OnReceiveScore();
}

    public void  OnReceiveScore()收到服务器端发送的分数
    {
        int score = Random.Range(0, 100);
        dispatcher.Dispatch(Demo1ServiceEvent.RequestScore, score);//通过Demo1CommandEvent.RequeestScore这个事件将数据发送出去
    }

 

于是控制台打印出Request Score from url:http://xx/xx/xxx

同时在执行OnReceiveScore时由于发送了Demo1ServiceEvent.RequestScore事件,承接上文于是调用RequestscoreCommand的OnComplete方法

Debug.Log("request score complete"+evt.data);
scoreService.dispatcher.RemoveListener(Demo1ServiceEvent.RequestScore, OnComplete);//移除对OnComplete的监听
scoreModel.score = (int)evt.data;
dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, evt.data);

Model层保存数据,发送一个Demo1MediatorEvent.ScoreChange事件,不要忘了在CubeMediator中对这个事件是有监听的,触发OnScoreChange方法,执行对CubeView的操作

cubeView.Updatescore((int)evt.data);
 

而当鼠标点击CubeView上时,调用CubeView中的OnMouseDown方法:

Debug.Log("OnMouDown");

audioManager.playAudio("explosive");

dispacher.Dispatch(Demo1MediatorEvent.ClickDown);

控制台打印OnMouDown,同时播放音效,然后发送Demo1MediatorEvent.ClickDown事件,谁来接收呢?

在CubeMediator中有过接收:

dispatcher.Dispatch(Demo1CommandEvent.UpdateScore);

但不做处理,发出Demo1CommandEvent.UpdateScore事件,被UpdateScoreCommand所接收,执行Execute方法:

ScoreModel.score++;

scoreServer.UpdateScore("http://xx/xx", ScoreModel.score);

dispatcher.Dispatch(Demo1MediatorEvent.ScoreChange, ScoreModel.score);

Model层更新数据,Server层更新分数,实际上只是打印输出,发出Demo1MediatorEvent.ScoreChange事件,又重新被CubeMediator类捕获到,执行

public void OnScoreChange(IEvent evt)
{
        cubeView.Updatescore((int)evt.data);

}

由CubeView执行更新UI的操作。

 

(2)带Event前缀,例如EventCommand,EventView,EventMediator都可以直接访问到dispatcher,而无需再注入一个dispacher,类似全局变量和局部变量。

 

(3)在进行绑定时:Model层和Server层后面加了ToSingleton();

Inject注入,实际上就类似于声明一个变量。

 

Demo下载地址:https://download.csdn.net/download/dmk17771552304/10776694

原文链接在这里https://www.jianshu.com/p/663a36dce0de,但是他写的有问题,在后面我又重新梳理了一下整个运行逻辑。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值