主要内容
- MVC基础
- MVC变形–MVX概念
- Pure MVC框架
基本概念
数据、界面、逻辑分离
游戏中的应用: 非必须的UI系统开发框架
MVX
MVP: 断开model和view层的耦合
MVVM:数据双向绑定
MVE:基于事件分发
PureMVC
基本结构:MVC+Proxy+Mediator+Command+Facade
导入
- 方式一:生成dll文件直接导入
- 方式二:导入Core、Interface、Patterns三个文件夹
第一步:创建一个通知名类
1 2 3 4 5 6 7 8 9
|
public class MyNotification { public const string SHOW_PANEL = "showPanel"; public const string UPDATE_PLAYER_INFO = "updatePlayerInfo"; public const string START_GAME = "startGame"; }
|
创建 Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class PlayerDataObj { public string playerName; public int lev; public int money; public int gem; public int power; public int hp; public int atk; public int def; public int crit; public int miss; public int luck; }
|
Proxy
- 代理类继承
Proxy
基类
- 构造函数需要初始化属性:代理的名字
Name
、数据Data
保存Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
public class PlayerProxy : Proxy { public new const string NAME = "PlayerProxy";
public PlayerProxy():base(PlayerProxy.NAME) { PlayerDataObj data = new PlayerDataObj();
data.playerName = PlayerPrefs.GetString("PlayerName", "唐老狮"); data.lev = PlayerPrefs.GetInt("PlayerLev", 1); data.money = PlayerPrefs.GetInt("PlayerMoney", 9999); data.gem = PlayerPrefs.GetInt("PlayerGem", 8888); data.power = PlayerPrefs.GetInt("PlayerPower", 99);
data.hp = PlayerPrefs.GetInt("PlayerHp", 100); data.atk = PlayerPrefs.GetInt("PlayerAtk", 20); data.def = PlayerPrefs.GetInt("PlayerDef", 10); data.crit = PlayerPrefs.GetInt("PlayerCrit", 20); data.miss = PlayerPrefs.GetInt("PlayerMiss", 10); data.luck = PlayerPrefs.GetInt("PlayerLuck", 40);
Data = data; }
public void LevUp() { PlayerDataObj data = Data as PlayerDataObj;
data.lev += 1;
data.hp += data.lev; data.atk += data.lev; data.def += data.lev; data.crit += data.lev; data.miss += data.lev; data.luck += data.lev; }
public void SaveData() { PlayerDataObj data = Data as PlayerDataObj; PlayerPrefs.SetString("PlayerName", data.playerName); PlayerPrefs.SetInt("PlayerLev", data.lev); PlayerPrefs.SetInt("PlayerMoney", data.money); PlayerPrefs.SetInt("PlayerGem", data.gem); PlayerPrefs.SetInt("PlayerPower", data.power);
PlayerPrefs.SetInt("PlayerHp", data.hp); PlayerPrefs.SetInt("PlayerAtk", data.atk); PlayerPrefs.SetInt("PlayerDef", data.def); PlayerPrefs.SetInt("PlayerCrit", data.crit); PlayerPrefs.SetInt("PlayerMiss", data.miss); PlayerPrefs.SetInt("PlayerLuck", data.luck); } }
|
- 继承
Mediator
类
- 构造函数:名字(必须)、View界面脚本(可选)
- 重写监听通知的方法
ListNotificationInterests
,返回需要监听的事件名的string
数组
- 重写处理通知的方法
HandleNotification
,参数为INotification
对象(包含通知名和数据信息)
- 重写注册方法
OnRegister
(可选)
View:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class NewMainView : MonoBehaviour { public Button btnRole; public Button btnSill;
public Text txtName; public Text txtLev; public Text txtMoney; public Text txtGem; public Text txtPower;
public void UpdateInfo(PlayerDataObj data) { txtName.text = data.playerName; txtLev.text = "LV." + data.lev; txtMoney.text = data.money.ToString(); txtGem.text = data.gem.ToString(); txtPower.text = data.power.ToString(); } }
|
Mediator:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public class NewMainViewMediator : Mediator { public static new string NAME = "NewMainViewMediator"; public NewMainViewMediator():base(NAME) { }
public void SetView(NewMainView view) { ViewComponent = view; view.btnRole.onClick.AddListener(()=> { SendNotification(PureNotification.SHOW_PANEL, "RolePanel"); }); }
public override string[] ListNotificationInterests() { return new string[]{ PureNotification.UPDATE_PLAYER_INFO, }; }
public override void HandleNotification(INotification notification) { switch (notification.Name) { case PureNotification.UPDATE_PLAYER_INFO: if(ViewComponent != null) { (ViewComponent as NewMainView).UpdateInfo(notification.Body as PlayerDataObj); } break; } }
public override void OnRegister() { base.OnRegister(); } }
|
Facade和Command执行流程
Command:
- 继承
SimpleCommand
- 重写执行函数
Execute
,参数INotification
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class StartUpCommand : SimpleCommand { public override void Execute(INotification notification) { base.Execute(notification);
if( !Facade.HasProxy(PlayerProxy.NAME) ) { Facade.RegisterProxy(new PlayerProxy()); } } }
|
Facade:
- 继承
Facade
- 为了方便使用,写一个单例模式道的属性
- 初始化控制层相关内容(注册命令)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| public class GameFacade : Facade {
public static GameFacade Instance { get { if( instance == null ) { instance = new GameFacade(); } return instance as GameFacade; } }
protected override void InitializeController() { base.InitializeController(); RegisterCommand(PureNotification.START_UP, () => { return new StartUpCommand(); });
RegisterCommand(PureNotification.SHOW_PANEL, () => { return new ShowPanelCommand(); });
RegisterCommand(PureNotification.HIDE_PANEL, () => { return new HidePanelCommand(); });
RegisterCommand(PureNotification.LEV_UP, () => { return new LevUpCommand(); }); }
public void StartUp() { SendNotification(PureNotification.START_UP); } }
|
总结
Proxy、Mediator、Command都注册到Facede,Mediator主要注册通知名和界面通知处理、Command主要逻辑处理、Facede主要注册和获取其他三类以及发送通知等
1.先数据 2.再界面 3.再用命令做串联 4.Facede判断、注册和获取