StrangeIoc是一款基于MVCS的一种框架,是对MVC思想的扩展,是专门针对Unity开发的一款框架。下面是官方提供的结构图,类似于UML图。
以自己的项目为例:
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的文档,未完待完善。