美文网首页
PureMVC框架

PureMVC框架

作者: 莫忘初心_倒霉熊 | 来源:发表于2020-08-02 17:33 被阅读0次

PureMVC框架讲解

1. 理论基础

Pure MVC是在基于模型、视图和控制器MVC模式建立的一个轻量级的应用框架,这个框架是开源免费的,目前支持18中开发语言。

  1. 应用PureMVC主要目的就是“解耦”,除了层之间的解耦外,我们也可 以在层内,进行进一步的划分。
  2. 模型层一般都分为:“数据实体类(值对象)”与“数据代理类” 好处是,“数据本身”与“数据操作”相分离,易于存储、扩展等,耦合性降低与扩展性提高。
  3. 视图层也可以基于降低“层内”的耦合性的思想分为:“显示View” 与“显示控制 Mediator”,View : 只负责简单的窗体数据显示;Mediator:负责显示层的通讯、按钮点击事件、数据处理。

官网:http://puremvc.org
github地址:https://github.com/PureMVC

1.1 PureMVC整体架构

官方整体架构图.png
  • Model 与 Proxy
    Model保存对Proxy对象的引用,Proxy负责操作数据模型,存取数据。这样保证了Model层的可移植性。
  • View 与 Mediator
    View保存对Mediator对象的引用。由Mediator对象来操作具体的视图组件(View Component),包括:添加事件监听器,发送或接收Notification ,直接改变视图组件的状态。这样做实现了把视图和控制它的逻辑分离开来。
  • Controller 与 Command
    Controller保存所有Command的映射。Command类是无状态的,只在需要时才被创建。
    Command可以获取Proxy对象并与之交互,发送Notification,执行其他的Command。经常用于复杂的或系统范围的操作,如应用程序的“启动”和“关闭”。应用程序的业务逻辑应该在这里实现。
  • Facade 与 Model,View和Controller
    Facade类应用单例模式,它负责初始化核心层(Model,View和Controller),并能访问它们的Public方法。在实际的应用中,只需继承Facade类创建一个具体的Facade类就可以实现整个MVC模式,并不需要在代码中导入编写Model,View和Controller类。
    Proxy、Mediator和Command就可以通过创建的Facade类来相互访问通信。

1.2 设计模式

  1. 单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  2. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。

  3. 中介者模式(Mediator):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

迪米特法则(Law of Demeter,简称LoD)也叫最小知识原则(Least Knowledge Principle 简写LKP)如果俩个类不必直接通信,那么这俩类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

  1. 命令模式(Command):讲一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

  2. 外观模式(Facade):为了系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

  3. 观察者模式(Publish/Subscribe):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

1.3 数据通信

数据通信.png

2. 一个简单的案例

2.1 PureMVC架构基本的开发流程:

  1. 定义自己的ApplicationFacade类(继承Facade)
    1)注册控制层类,以及定义“消息名称”与命令类的绑定关系
    2)注册模型层类
    3)注册视图层类
  2. 定义自己的类
    1)模型层类(继承Proxy)
    2)视图层类(继承Mediator)
    3)控制层类 (继承SimpleCommand或者MacroCommand)
  3. 确定层之间的消息传递。
  4. 调试项目。

2.2 案例介绍

demo地址:https://gitee.com/ZhaoYongshuang/puremvc_framework_demo

简单案例.png

2.3 代码实现

2.3.1 ApplicationFacade.cs

using PureMVC.Patterns;
using PureMVC.Interfaces;

public class ApplicationFacade :Facade
{
    public new static IFacade Instance
    {
        get
        {
            if (m_instance == null)
            {
                lock (m_staticSyncRoot)
                {
                    if (m_instance == null)
                    {
                        m_instance = new ApplicationFacade();
                    }
                }
            }
            return m_instance;
        }
    }
    protected override void InitializeModel()
    {
        base.InitializeModel();
        RegisterProxy(new MyProxy());
    }
    protected override void InitializeView()
    {
        base.InitializeView();
        RegisterMediator(new MyMediator());
    }
    protected override void InitializeController()
    {
        base.InitializeController();
        RegisterCommand("Cmd_StartUpApp", typeof(CmdStartUpApp));
        RegisterCommand("Cmd_AddCount", typeof(CmdAddCount));
    }
}

2.3.2 MyUI.cs

using System;
using UnityEngine;
using UnityEngine.UI;

public class MyUI : MonoBehaviour
{
    private Text txtLevel;
    private Button btnAddCount;

    public Action actionBtnCount;
    void Start()
    {
        txtLevel = transform.Find("TxtCount").gameObject.GetComponent<Text>();
        btnAddCount = transform.Find("BtnCount").gameObject.GetComponent<Button>();
        btnAddCount.onClick.AddListener(OnClickAddCount);
    }
    private void OnClickAddCount()
    {
        actionBtnCount?.Invoke();
    }
    public void SetTxtCount(MyData myData)
    {
        txtLevel.text = myData.Count.ToString();
    }
}

2.3.3 StartGame.cs

using UnityEngine;

public class StartGame : MonoBehaviour {
    public MyUI myUI;

    void Start()
    {
        ApplicationFacade appFacade = ApplicationFacade.Instance as ApplicationFacade;
        if (appFacade != null && myUI != null)
        {
            appFacade.SendNotification("Cmd_StartUpApp", myUI);
        }
    }
}

2.3.4 CmdStartUpApp.cs

using PureMVC.Interfaces;
using PureMVC.Patterns;

public class CmdStartUpApp : SimpleCommand
{
    public override void Execute(INotification notification)
    {
        MyUI myUI = notification.Body as MyUI;
        if(myUI != null)
        {
            SendNotification("Msg_InitMyUI",myUI); 
        }
    }
}

2.3.5 MyMediator.cs

using System.Collections.Generic;
using PureMVC.Interfaces;
using PureMVC.Patterns;

public class MyMediator : Mediator {
    public new const string NAME = "MyMediator";

    private MyUI myUI
    {
        get
        {
            return base.ViewComponent as MyUI;
        }
    }
    public override IList<string> ListNotificationInterests()
        {
            IList<string> listResult=new List<string>();
        listResult.Add("Msg_InitMyUI");
        listResult.Add("Msg_AddCount");
            return listResult;
        }
        public override void HandleNotification(INotification notification)
        {
        switch (notification.Name)
        {
            case "Msg_InitMyUI":
                MyUI myUI = notification.Body as MyUI;
                this.InitMyUIMediator(myUI);
                break;
            case "Msg_AddCount":
                MyData myData = notification.Body as MyData;
                this.AddCount(myData);
                break;
            default:
                break;
        }
        }
    private void InitMyUIMediator(MyUI myUI)
    {
        if (myUI != null)
        {
            base.m_mediatorName = NAME;
            base.m_viewComponent = myUI;
            myUI.actionBtnCount = this.OnClickAddCount;
        }
    }
    private void OnClickAddCount()
    {
        SendNotification("Cmd_AddCount");
    }
    private void AddCount(MyData myData)
    {
        this.myUI.SetTxtCount(myData);
    }
}

2.3.6 CmdAddCount.cs

using PureMVC.Interfaces;
using PureMVC.Patterns;

public class CmdAddCount :SimpleCommand {
    public override void Execute(INotification notification)
    {
        MyProxy myProxy = (MyProxy)Facade.RetrieveProxy(MyProxy.NAME);
        myProxy.AddLevel(10);
    }
}

2.3.7 MyData.cs

public class MyData
{
    private int _count = 0;

    public int Count
    {
        get { return _count; }
        set { _count = value; }
    }
}

2.3.8 MyProxy.cs

using PureMVC.Patterns;

public class MyProxy :Proxy {
    public new const string NAME = "MyProxy";
        private MyData myData = null;

        public MyProxy():base(NAME)
        {
        myData = new MyData();
        }
    public void AddLevel(int addNumber)
    {
        myData.Count += addNumber;
        SendNotification("Msg_AddCount", myData);
    }
}

2.4 消息流程

案例消息流程图.png

3 框架源码分析

源码在上面的demo中有,可自行下载查看

3.1 源码文件结构

源码文件.png

3.2 源码消息流程

源码消息流程.png
  • Controller保存了Command与Notification之间的映射。当Notification(通知)被发出时,对应的Command(命令)就会自动地由Controller执行。Command实现复杂的交互,降低View和Model之间的耦合度。
  • Mediator发送、声明、接收Notification。当用View注册Mediator时,Mediator的ListNotificationInterests方法会被调用,以list形式返回该Mediator对象所关心的所有Notification。之后,当系统其它角色发出同名的Notification(通知)时,关心这个通知的Mediator都会调用handleNotification方法并将Notification以参数传递到方法。
  • Proxy发送,但不接收Notification。在很多场合下Proxy需要发送Notification(通知),比如:Proxy从远程服务器接收到数据时,发送Notification告诉系统;或当Proxy的数据被更新时,发送Notification告诉系统。

3.3 模块图

PureMVC源码整体架构图.png

相关文章

网友评论

      本文标题:PureMVC框架

      本文链接:https://www.haomeiwen.com/subject/dyoprktx.html