UMVCSL7——PureMVC框架UI实例 
注意!需要先将前面6节课的内容看完再来接着看这里的内容 
本章代码关键字 
1 2 3 4 5 6 7 8 Notifier.Facade                 Notifier.SendNotification()     Facade.HasMediator()            Facade.RegisterMediator()       Facade.RetrieveMediator()       Facade.HasProxy()               Facade.RegisterProxy()          Facade.RetrieveProxy()          
 
显示面板 
将一个Command命令与显示面板的通知绑定 
在该Command命令的Execute()方法内实现显示面板 
首先检测是否注册过Mediator,没有就注册Mediator,并将该Mediator关联到View控件 
通过Mediator来执行显示面板方法 
 
首先我们需要声明一个ShowPanelCommand的命令,在该命令里实现显示面板的方法
1 2 3 4 5 6 7 8 9 10 11 12 using  PureMVC.Interfaces;using  PureMVC.Patterns.Command;using  UnityEngine;public  class  ShowPanelCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);              } } 
 
然后将该命令在Facade类里注册,与SHOW_PANEL这个通知绑定
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 using  PureMVC.Patterns.Facade;public  class  GameFacade  : Facade {                                   public  static  GameFacade Instance => (instance ??= new  GameFacade()) as  GameFacade;          protected  override  void  InitializeController ()     {         base .InitializeController();                  RegisterCommand(PureNotification.START_UP, () => { return  new  StartUpCommand(); });         RegisterCommand(PureNotification.SHOW_PANEL, () => { return  new  ShowPanelCommand(); });     }          public  void  StartUp ()     {                  SendNotification(PureNotification.START_UP);       } } 
 
接下来即可在ShowPanelCommand内实现显示面板的方法 
我们可以通过Execute()传入的notification.body(通知者传入的对象参数)来判断显示的是哪个面板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using  UnityEngine;public  class  Main  : MonoBehaviour {     void  Start ()     {         GameFacade.Instance.StartUp();     }     void  Update ()     {         if  (Input.GetKeyDown(KeyCode.M))         {                          GameFacade.Instance.SendNotification(PureNotification.SHOW_PANEL, "MainPanel" );         }     } } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public  class  ShowPanelCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);                  string  panelName = notification.Body.ToString();         switch  (panelName)         {             case  "MainPanel" :                 break ;             case  "RolePanel" :                 break ;         }     } } 
 
继承了Notifier的类(SimpleCommand、Mediator、Proxy都继承了该类)可以使用Facade,以直接调用场景上唯一的Facade 
因此可以在命令中直接使用Facade代表的就是唯一的Facade
调用Facade可以注册Mediator,以及判断一个Mediator是否被注册 
注意!如果要使用Mediator,一定也要在 Facade 中去注册, command  、 proxy 也一样,如果要通过 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 public  class  ShowPanelCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);                  string  panelName = notification.Body.ToString();         switch  (panelName)         {             case  "MainPanel" :                                                                                                                       if  (!Facade.HasMediator(NewMainViewMediator.NAME))                     Facade.RegisterMediator(new  NewMainViewMediator());                 break ;             case  "RolePanel" :                 break ;         }     } } 
 
有mediator之后,就是可以创建界面,创建预设体,并可以将界面的View控件,关联到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 60 using  PureMVC.Interfaces;using  PureMVC.Patterns.Command;using  UnityEngine;public  class  ShowPanelCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);                  string  panelName = notification.Body.ToString();                  switch  (panelName)         {             case  "MainPanel" :                                                                                                      if  (!Facade.HasMediator(NewMainViewMediator.NAME))                     Facade.RegisterMediator(new  NewMainViewMediator());                                                   NewMainViewMediator mainViewMediator = Facade.RetrieveMediator(NewMainViewMediator.NAME) as  NewMainViewMediator;                                  if  (mainViewMediator.ViewComponent == null )                 {                     GameObject res = Resources.Load<GameObject>("UI/MainPanel" );                     GameObject obj = GameObject.Instantiate(res);                                          obj.transform.SetParent(GameObject.Find("Canvas" ).transform, false );                                          mainViewMediator.ViewComponent = obj.GetComponent<NewMainView>();                 }                 break ;             case  "RolePanel" :                                                   if  (!Facade.HasMediator(NewRoleViewMediator.NAME))                     Facade.RegisterMediator(new  NewRoleViewMediator());                                                   NewRoleViewMediator roleViewMediator = Facade.RetrieveMediator(NewRoleViewMediator.NAME) as  NewRoleViewMediator;                                  if  (roleViewMediator.ViewComponent == null )                 {                     GameObject res = Resources.Load<GameObject>("UI/RolePanel" );                     GameObject obj = GameObject.Instantiate(res);                                          obj.transform.SetParent(GameObject.Find("Canvas" ).transform, false );                                          roleViewMediator.ViewComponent = obj.GetComponent<NewRoleView>();                 }                 break ;         }     } } 
 
我们还没有监听View的用户输入行为,在可以在Mediator里设置监听(甚至可以不用在Command内执行关联) 
继承了Notifier的类(SimpleCommand、Mediator、Proxy都继承了该类)可以直接使用SendNotification()
1 2 3 4 5 6 7 8 public  void  SetView (NewMainView view ){     ViewComponent = view;     view.btnRole.onClick.AddListener(() =>     {         SendNotification(PureNotification.SHOW_PANEL, "RolePanel" );     }); } 
 
1 2 3 4 5 6 7 8 9 if  (mainViewMediator.ViewComponent == null ){     GameObject res = Resources.Load<GameObject>("UI/MainPanel" );     GameObject obj = GameObject.Instantiate(res);          obj.transform.SetParent(GameObject.Find("Canvas" ).transform, false );          mainViewMediator.SetView(obj.GetComponent<NewMainView>()); } 
 
隐藏面板 
将一个Command命令与隐藏面板的通知绑定 
在该Command命令的Execute()方法内实现隐藏面板 
得到Mediator再得到Mediator中的View 
通过View来删除或隐藏UI对象 
 
隐藏的目的,得到Mediator再得到Mediator中的View,通过View来删除或隐藏UI对象 
这里通过外部通知者传入要隐藏面板的Mediator
注:这里notification.Body is Mediator mediator使用了模式匹配的类型模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 using  PureMVC.Interfaces;using  PureMVC.Patterns.Command;using  PureMVC.Patterns.Mediator;using  UnityEngine;public  class  HidePanelCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);                           if  (notification.Body is  Mediator mediator && mediator.ViewComponent != null )         {                          GameObject.Destroy((mediator.ViewComponent as  MonoBehaviour).gameObject);                          mediator.ViewComponent = null ;         }     } } 
 
之后再在外部使用通知隐藏面板即可
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 using  UnityEngine;public  class  Main  : MonoBehaviour {          void  Start ()     {         GameFacade.Instance.StartUp();     }          void  Update ()     {         if  (Input.GetKeyDown(KeyCode.M))         {                          GameFacade.Instance.SendNotification(PureNotification.SHOW_PANEL, "MainPanel" );         }         else  if  (Input.GetKeyDown(KeyCode.N))         {                          GameFacade.Instance.SendNotification(PureNotification.HIDE_PANEL, GameFacade.Instance.RetrieveMediator(NewMainViewMediator.NAME));         }     } } 
 
我们还没有监听View的用户输入行为,在可以在Mediator里设置监听(甚至可以不用在Command内执行关联) 
继承了Notifier的类(SimpleCommand、Mediator、Proxy都继承了该类)可以直接使用SendNotification()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 using  PureMVC.Interfaces;using  PureMVC.Patterns.Mediator;public  class  NewRoleViewMediator  : Mediator {     public  void  SetView (NewRoleView view )     {         ViewComponent = view;         view.btnClose.onClick.AddListener(() =>         {             SendNotification(PureNotification.HIDE_PANEL, this );         });         view.btnLevUp.onClick.AddListener(() =>         {                      });     } } 
 
更新通知 
往往显示了面板后,需要在这里进行第一次UI控件更新,就需要把数据作为参数一起传出去 
但是目前的Facade是没有Proxy的数据的,因此我们需要为Proxy注册,我们一般在启动函数里注册Proxy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 using  PureMVC.Patterns.Facade;public  class  GameFacade  : Facade {          public  void  StartUp ()     {                  SendNotification(PureNotification.START_UP);                           if  (!HasProxy(PlayerProxy.NAME))              RegisterProxy(new  PlayerProxy());     } } 
 
之后就可以通过Facade调用RetrieveProxy()方法传入PlayerProxy.NAME来获取Proxy,进而通过Proxy.data来获取数据 
同时要注意,通知是不一定需要和command命令绑定在一起的,在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 public  class  NewMainViewMediator  : Mediator  {          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:                 (ViewComponent as  NewMainView).UpdateInfo(notification.Body as  PlayerDataObject);                 break ;         }     } } public  class  NewRoleViewMediator  : Mediator {     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:                 (ViewComponent as  NewRoleView).UpdateInfo( notification.Body as  PlayerDataObject );                 break ;         }     } } 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public  override  void  Execute (INotification notification ){     base .Execute(notification);          string  panelName = notification.Body.ToString();     switch  (panelName)     {         case  "MainPanel" :                                       SendNotification(PureNotification.UPDATE_PLAYER_INFO, Facade.RetrieveProxy(PlayerProxy.NAME).Data);             break ;         case  "RolePanel" :                          SendNotification(PureNotification.UPDATE_PLAYER_INFO, Facade.RetrieveProxy(PlayerProxy.NAME).Data);             break ;     } } 
 
接下来监听升级按钮的输入,实现升级的方法
这里我们再声明一个用于升级的LevUpCommand命令,以及对应的通知,并在Facade内注册它
1 2 3 4 public  class  PureNotification {     public  const  string  LEVEL_UP = "levelUp" ; } 
 
注:这里Facade.RetrieveProxy(PlayerProxy.NAME) is PlayerProxy playerProxy使用了模式匹配的类型模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 using  PureMVC.Interfaces;using  PureMVC.Patterns.Command;public  class  LevUpCommand  : SimpleCommand {     public  override  void  Execute (INotification notification )     {         base .Execute(notification);         if  (Facade.RetrieveProxy(PlayerProxy.NAME) is  PlayerProxy playerProxy)         {                          playerProxy.LevelUp();                          SendNotification(PureNotification.UPDATE_PLAYER_INFO, playerProxy.Data);         }     } } 
 
1 2 3 4 5 6 7 8 9 10 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.LEVEL_UP, () => { return  new  LevUpCommand(); }); } 
 
之后在Mediator内监听升级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  void  SetView (NewRoleView view ){     ViewComponent = view;     view.btnClose.onClick.AddListener(() =>     {         SendNotification(PureNotification.HIDE_PANEL, this );     });     view.btnLevUp.onClick.AddListener(() =>     {                  SendNotification(PureNotification.LEVEL_UP);     }); } 
 
值得一提的是,Mediator内每次对其关联的ViewComponent进行操作时,都应当判空,避免出现问题
1 2 3 4 5 6 7 8 9 10 11 public  override  void  HandleNotification (INotification notification ){     switch  (notification.Name)     {         case  PureNotification.UPDATE_PLAYER_INFO:             if  (ViewComponent != null )                 (ViewComponent as  NewRoleView).UpdateInfo( notification.Body as  PlayerDataObject );             break ;     } }