Unity笔记——浅谈StrangeIoc框架

首要知道什么是MVCS

1、M  即Model 是本地数据类型 比如从服务器、表、xml等获得的数据赋值给model,以后再取用数据时直接读取model对象即可。一般为单例的对象。
2、V  即View  是视图    一般就是UI这一块,在StrangeIoc中View一般以组件的形式挂在物体身上的,负责查找UI上需要交互的对象。并且在view中提供更新UI的方法。
3、C  即Command  是命令   在Strangeioc中会和事件绑定,绑定后只要触发事件就会执行对应的Command,Command是框架的核心 负责和service、model 以及 Mediator(中间层)的交互。
4、S  即Service   是服务层  属于服务端数据,请求数据,更新数据,保存数据等。

StrangeIoc是一款基于MVCS的一种框架,是对MVC思想的扩展,是专门针对Unity开发的一款框架。下面是官方提供的结构图,类似于UML图。

Unity笔记——浅谈StrangeIoc框架_第1张图片


简单分析

以自己的项目为例:

1、Root 是整个框架的起点,是要挂载在物体上的,继承自ContextView,而ContextView继承自MonoBehaviour,相当于ContextView间接继承自MonoBehaviour,而他的主要功能是创建Context。

public class GameRoot : ContextView {
     void Awake()
    {
        context = new GameContext(this,true);//开启框架
        context.Start();
    }
}

2、Context这个类继承自MVCSContext,主要功能负责进行绑定 mapBinding。

public class GameContext : MVCSContext {
    public GameContext(MonoBehaviour view, bool autoMapping) : base(view, autoMapping)
    {

    }
    /// 
    /// 绑定映射
    /// 
    protected override void mapBindings()
    {
        Debug.Log("框架启动成功");
        base.mapBindings();
        //确保所有的其他控制器脚本能获取 IntegrationModel
        injectionBinder.Bind().To().ToSingleton();

        mediationBinder.Bind().To();
        mediationBinder.Bind().To();
        mediationBinder.BindView().ToMediator();
        commandBinder.Bind(CommandEvent.ChangeMultiple).To();

        commandBinder.Bind(CommandEvent.GrabLandLord).To();//玩家抢地主

        commandBinder.Bind(CommandEvent.GameOver).To();
        commandBinder.Bind(CommandEvent.RequestUpdate).To();

        commandBinder.Bind(CommandEvent.PlayCard).To();
        commandBinder.Bind(CommandEvent.PassCard).To();

        commandBinder.Bind(NoThanks.PlayerBuchu).To();
        //开始命令 ContextEvent.START框架封装 
        commandBinder.Bind(ContextEvent.START).To().Once();

        //确保所有的其他控制器脚本 能获取 CardModel
        injectionBinder.Bind().To().ToSingleton();
        injectionBinder.Bind().To().ToSingleton();

        commandBinder.Bind(CommandEvent.RequestDeal).To();
    }
}

从中我们分开来看:

injectionBinder.Bind().To().ToSingleton();

模型数据绑定为单例模式

commandBinder.Bind(CommandEvent.GrabLandLord).To();//玩家抢地主

绑定事件命令 命令可以自定义 当dispatchar这个命令时,GrabLandlordCommand里的execute方法就会执行

mediationBinder.Bind().To();

视图层和中间层绑定

//开始命令 ContextEvent.START框架封装 
        commandBinder.Bind(ContextEvent.START).To().Once();

绑定一个StartCommand事件 这个时间 是框架里定义的 是开始命令


3、Mediator类负责和UI、Command进行交互

举上文曾出现的CharacterMediator为例子。

public class CharacterMediator :EventMediator {

	[Inject]

    public CharacterView CharacterView { get; set; }//注入CharacterView

    public override void OnRegister() //View创建 mediator就会创建 这个方法就会执行
    {
        CharacterView.Init();
        //以下是给事件添加监听,以及回调函数
        dispatcher.AddListener(CommandEvent.DealCard,onDealCard);//发牌事件
        dispatcher.AddListener(ViewEvent.COMPLETE_DEAL,onCompleteDeal);
        dispatcher.AddListener(ViewEvent.DEAL_THREECARD, onDealThreeCard);//监听抢地主
        dispatcher.AddListener(ViewEvent.REQUEST_PLAY,onPlayerPlayCard);
        dispatcher.AddListener(ViewEvent.SUCCESSED_PLAY,onPlayerSuccessPlay);

        //重新开始
        dispatcher.AddListener(ViewEvent.RESTART_GAME, onRestartGame);
        //更新积分
        dispatcher.AddListener(ViewEvent.UPDATE_INTEGRATION, onUpdateIntegration);

        RoundModel.ComputerHandler += RoundModel1_ComputerHandler;
    }

   

    public void onDealCard(IEvent evt) {
        DealCardArgs e = evt.data as DealCardArgs;
        CharacterView.AddCard(e.cType,e.card,e.selected);
    }
    //当View销毁 mediator就会销毁 这个方法就会被执行
    public override void OnRemove()
    {
        base.OnRemove();
        dispatcher.RemoveListener(CommandEvent.DealCard,onDealCard);
        dispatcher.RemoveListener(ViewEvent.COMPLETE_DEAL,onCompleteDeal);
        dispatcher.RemoveListener(ViewEvent.DEAL_THREECARD,onDealThreeCard);
        dispatcher.RemoveListener(ViewEvent.REQUEST_PLAY,onPlayerPlayCard);
        dispatcher.RemoveListener(ViewEvent.SUCCESSED_PLAY,onPlayerSuccessPlay);

        dispatcher.RemoveListener(ViewEvent.RESTART_GAME, onRestartGame);
        dispatcher.RemoveListener(ViewEvent.UPDATE_INTEGRATION, onUpdateIntegration);

        RoundModel.ComputerHandler -= RoundModel1_ComputerHandler;
    }

    public void onCompleteDeal() {
        CharacterView.Player.Sort(false);
        CharacterView.Desk.Sort(true);
    }
    /// 
    /// 发底牌
    /// 
    /// 
    public void onDealThreeCard(IEvent evt) {
        GrabLandlordArgs e = evt.data as GrabLandlordArgs;
        CharacterView.AddThreeCard(e.cType);
        CharacterView.Player.Sort(false);
    }
    /// 
    /// 玩家请求出牌
    /// 
    public void onPlayerPlayCard() {
        List cardList = CharacterView.Player.FindSelectCard();//寻找选中手牌方法 存放在集合中
        CardType cardType;
        Rulers.CanPop(cardList,out cardType);//检测 玩家选中的牌 是否合法

        if (cardType!=CardType.None)
        {
            PlayCardArgs e = new PlayCardArgs()
            {
                cardType = cardType,
                characterType = CharacterType.Player,
                Length = cardList.Count,
                Weight = Tools.GetWeight(cardList,cardType)
            };

            dispatcher.Dispatch(CommandEvent.PlayCard,e);
            /*foreach (Card card in cardList)
            {
                CharacterView.AddCard(CharacterType.Desk,card,false);
            }*/
            //CharacterView.Player.DeleteSelectCard();//删除发出去的牌
            //dispatcher.Dispatch(ViewEvent.COMPLETE_PLAY);//派发 发牌结束事件
        }
        else
        {
            Debug.Log("不符合出牌规则,请选择正确牌");
        }
    }
    /// 
    /// 玩家成功出牌
    /// 
    private void onPlayerSuccessPlay()
    {
        List cardList = CharacterView.Player.FindSelectCard();
        CharacterView.Desk.Clear();
        foreach (Card card in cardList)
        {
            CharacterView.AddCard(CharacterType.Desk, card, false);
        }
        CharacterView.Player.DeleteSelectCard();

        //游戏胜利的判断
        if (!CharacterView.Player.HasCard)
        {
            Identity r = CharacterView.ComputerRight.Identity;
            Identity l = CharacterView.ComputerLeft.Identity;
            Identity p = CharacterView.Player.Identity;
            GameOverArgs eee = new GameOverArgs()
            {
                PlayerWin = true,
                ComputerRightWin = r == p ? true : false,
                ComputerLeftWin = l == p ? true : false
            };

            dispatcher.Dispatch(ViewEvent.COMPLETE_PLAY);
        }
        else
            dispatcher.Dispatch(ViewEvent.COMPLETE_PLAY);
    }

    /// 
    /// 更新积分的处理
    /// 
    private void onUpdateIntegration(IEvent evt)
    {
        GameDate data = evt.data as GameDate;
        CharacterView.Player.characterUI.SetIntergration(data.PlayerIntergration);
        CharacterView.ComputerLeft.characterUI.SetIntergration(data.ComLeftIntergration);
        CharacterView.ComputerRight.characterUI.SetIntergration(data.ComRigthintergration);
    }

    /// 
    /// 重新开始游戏
    /// 
    private void onRestartGame()
    {
        CharacterView.Player.CardList.Clear();
        CharacterView.ComputerLeft.CardList.Clear();
        CharacterView.ComputerRight.CardList.Clear();
        CharacterView.Init();
    }
    /// 
    /// 让电脑自动出牌
    /// 
    /// 
    private void RoundModel1_ComputerHandler(ComputerSmartArgs e)
    {
        StartCoroutine("DelayOneSecond",e);
    }
    /// 
    /// 延迟出牌
    /// 
    /// 
    /// 
    IEnumerator DelayOneSecond(ComputerSmartArgs e)
    {

        yield return new WaitForSeconds(1f);

        bool can = false;

        switch (e.CharacterType)
        {
            case CharacterType.ComputerRight:

                //电脑自动出牌的方法
                can = CharacterView.ComputerRight.ComputerSmartPlayCard(e.CardType, e.Weight,
                    e.Length, e.Biggest == CharacterType.ComputerRight);
                //出牌的检测
                if (can)
                {
                    //把右电脑选中的牌 存到集合里
                    List cardList =
                       CharacterView.ComputerRight.SelectCards;
                    CardType cardType = CharacterView.ComputerRight.CurrType;

                    //添加牌到桌面
                    CharacterView.Desk.Clear();
                    foreach (Card card in cardList)
                        CharacterView.AddCard(CharacterType.Desk, card, false);

                    //可以出牌
                    PlayCardArgs ee = new PlayCardArgs()
                    {
                        cardType = cardType,
                        characterType = CharacterType.ComputerRight,
                        Length = cardList.Count,
                        Weight = Tools.GetWeight(cardList, cardType)
                    };

                    //如果 手里 没牌了
                    if (!CharacterView.ComputerRight.HasCard)
                    {
                        Identity r = CharacterView.ComputerRight.Identity;
                        Identity l = CharacterView.ComputerLeft.Identity;
                        Identity p = CharacterView.Player.Identity;

                        GameOverArgs eee = new GameOverArgs()
                        {
                            ComputerRightWin = true,
                            ComputerLeftWin = l == r ? true : false,
                            PlayerWin = p == r ? true : false
                        };
                        dispatcher.Dispatch(CommandEvent.GameOver, eee);
                    }
                    else
                        dispatcher.Dispatch(CommandEvent.PlayCard, ee);
                }
                else
                {
                    dispatcher.Dispatch(CommandEvent.PassCard);
                }
                break;
            case CharacterType.ComputerLeft:
                can = CharacterView.ComputerLeft.ComputerSmartPlayCard(e.CardType, e.Weight, e.Length,
                    e.Biggest == CharacterType.ComputerLeft);
                //出牌的检测
                if (can)
                {
                    List cardList =
                       CharacterView.ComputerLeft.SelectCards;
                    CardType cardType = CharacterView.ComputerLeft.CurrType;

                    //添加牌到桌面
                    CharacterView.Desk.Clear();
                    foreach (Card card in cardList)
                        CharacterView.AddCard(CharacterType.Desk, card, false);

                    //可以出牌
                    PlayCardArgs ee = new PlayCardArgs()
                    {
                        cardType = cardType,
                        characterType = CharacterType.ComputerLeft,
                        Length = cardList.Count,
                        Weight = Tools.GetWeight(cardList, cardType)
                    };

                    if (!CharacterView.ComputerLeft.HasCard)
                    {
                        Identity r = CharacterView.ComputerRight.Identity;
                        Identity l = CharacterView.ComputerLeft.Identity;
                        Identity p = CharacterView.Player.Identity;
                        //游戏结束
                        GameOverArgs eee = new GameOverArgs()
                        {
                            ComputerLeftWin = true,
                            ComputerRightWin = r == l ? true : false,
                            PlayerWin = p == l ? true : false
                        };
                        dispatcher.Dispatch(CommandEvent.GameOver, eee);
                    }
                    else

                        //手里有牌,执行出牌操作    ee出牌的数据
                        dispatcher.Dispatch(CommandEvent.PlayCard, ee);
                }
                else
                {
                    //不能出牌  就  过Pass
                    dispatcher.Dispatch(CommandEvent.PassCard);
                }
                break;
            default:
                break;
        }
    }
}


4、Command类 

public class GrabLandlordCommand:EventCommand {
    [Inject]

    public InteGrationModel InteGrationModel { get; set; }

    [Inject]
    public RoundModel RoundModel { get; set; }

    public override void Execute()
    {
        GrabLandlordArgs e = this.evt.data as GrabLandlordArgs;
        InteGrationModel.Multiples *= 2;
        dispatcher.Dispatch(ViewEvent.DEAL_THREECARD,e);//在抢地主的时候 已经确定了角色, 把角色传递进

        RoundModel.StartGame(e.cType);
    }
}
5、View类  视图类

视图类会挂在对应的物体上 只会和对应的mediator进行交互

public class CharacterView :View {
    public PlayerController Player;

    public ComputerController ComputerLeft;

    public ComputerController ComputerRight;

    public DeskController Desk;

    public void Init()
    {
        Player.Identity = Identity.Farmer;
        ComputerLeft.Identity = Identity.Farmer;
        ComputerRight.Identity = Identity.Farmer;
    }
    /// 
    /// 添加卡牌
    /// 
    /// 
    /// 
    /// 
    public void AddCard(CharacterType cType,Card card,bool selected) {
        switch (cType)
        {
            case CharacterType.Library:
                
                break;
            case CharacterType.Player:
                Player.AddCard(card, selected);
                break;
            case CharacterType.ComputerRight:
                ComputerRight.AddCard(card,selected);
                break;
            case CharacterType.ComputerLeft:
                ComputerLeft.AddCard(card,selected);
                break;
            case CharacterType.Desk:
                Desk.AddCard(card,selected);
                break;
            default:
                break;
        }
    }
    /// 
    /// 添加底牌
    /// 
    /// 
    public void AddThreeCard(CharacterType cType) {
        Card card = null;
        switch (cType)
        {
            case CharacterType.Library:
                break;
            case CharacterType.Player:
                for (int i = 0; i < 3; i++)
                {
                    card = Desk.DealCard();
                    Player.AddCard(card,true);
                }
                Player.Identity = Identity.Landlord;
                Player.Sort(true);
                break;
            case CharacterType.ComputerRight:
                for (int i = 0; i < 3; i++)
                {
                    card = Desk.DealCard();
                    ComputerRight.AddCard(card,false);
                }
                ComputerRight.Identity = Identity.Landlord;
                ComputerRight.Sort(true);
                break;
            case CharacterType.ComputerLeft:
                for (int i = 0; i < 3; i++)
                {
                    card = Desk.DealCard();
                    ComputerLeft.AddCard(card, false);
                }
                ComputerLeft.Identity = Identity.Landlord;
                ComputerLeft.Sort(true);
                break;
            case CharacterType.Desk:
                break;
            default:
                break;
        }
        Desk.Clear();
    }

   
}

6、Service类

服务端接口 定义一些方法 项目中并没有用到,这里不再贴图。

7、Model 对本地数据的保存

public class InteGrationModel {
    /// 
    /// 底分
    /// 
    public int BasePoint;
    /// 
    /// 倍数
    /// 
    public int Multiples;
    /// 
    /// 总分属性
    /// 
    public int Result {
        get {
            return BasePoint * Multiples;
        }
    }

    public int PlayerIntegration;

    public int ComputerLeftIntegration;

    public int ComputerRightIntegration;
    /// 
    /// 初始化积分信息
    /// 
    public void InitIntegration() {
        PlayerIntegration = 1000;
        ComputerLeftIntegration = 1000;
        ComputerRightIntegration = 1000;

        Multiples = 1;
        BasePoint = 100;
    }
}

代码执行

1、首先是ContextView会创建一个context,紧接着context会进行bind,之后当前面的类进行创建时,bind的类会按照你指定的规则自动创建。

2、程序会在框架中Start命令执行ContextEvent.START绑定的Command里的Execute方法。

3、View会创建,Mediator类随着View类创建,执行OnRegister方法。

其他部分

1、Bind是StrangeIoc框架的重要功能,意思为绑定功能,在context中做绑定,可以绑定类——类,接口——类,类——方法,事件还有命令等。

2、Inject  StrangeIoc是依赖注入的框架,Inject就是注入,他的功能是当我们想要获取某种类型的对象时,我们不需要去创建,只需要加上[Inject]就可以根据bind时的规则获得对象。

3、Mediator 中间层负责和UI层、Command之间交互,它隔离了UI和逻辑,UI只能和Mediator交互。

4、dispatcher 派发器,是StrangeIoc实现消息派发的机制,分为全局和局部,全局dispatcher可以在任何地方发送消息,发送消息后会触发消息回调机制。然而局部的dispatcher通过对象进行发送消息,需要在Mediator中进行注册消息,并制定消息回调。


以上是通过项目对StrangeIoc的基本了解,从中参考了其他一些StrangeIoc的文档,未完待完善。

你可能感兴趣的:(Unity)