zoukankan      html  css  js  c++  java
  • 模式与架构系列之一:MVC

    1.MVC架构

    Model-View-Controller (MVC) 架构模式,可以分解为以下三个部件:

    模型:封装业务逻辑;

    视图:即界面(这里不啃概念)

    控制器:在视图与控制器间传递消息,使模型和视图协调工作。

     

    理想状况下,这种架构模式带来的好处是令人心动的。由于界面与业务逻辑的分离,降低了依赖性,使得逻辑代码可以完整地、轻松地被摘下来,用于别处。同时,控制器使用消息分发,可以轻易实现同时对多个界面产生影响。当然,这是理想状况

     

    2.一个MVC示例
    MVC模块的简要类图:


     


     


     


     


    1ModelElemen类实现ISenderIReceiver接口,可发送及接收消息,作为Model类的基类;
    2ViewElement类继承自Form类,并实现ISenderIReceiver接口,可发送及接收消息,作为View类的基类;
    3ControllerElement类实现ISenderIReceiverIController接口,可发送、接收及分发消息,作为Controller类的基类。

     

    配置文件:

    为了控制器最终能正确有效地向特定的一个或若干个ViewModel分发消息,系统用一个XML文件用于保存ModelViewController三者的关系,即完成所谓“注册”的功能,该XML文件结构类似如下:

      <ElementDefinetion>

    <FullName>xxProj.MainForm</FullName>

    <ShortName>MainForm</ShortName>

    <AssemblyName> xxProj </AssemblyName>

    <BelongedController>IndiController</BelongedController>

    <Type>View</Type>

      </ElementDefinetion>

      <ElementDefinetion>

        <FullName> xxProj.ActiveGrpCallList</FullName>

        <ShortName>ActiveGrpCallList</ShortName>

        <AssemblyName> xxProj </AssemblyName>

        <BelongedController>GrpCallController</BelongedController>

        <Type>View</Type>

      </ElementDefinetion>

      <ElementDefinetion>

        <FullName> xxProj.IndiCallModel</FullName>

        <ShortName>IndiCallModel</ShortName>

        <AssemblyName> xxProj </AssemblyName>

        <BelongedController>IndiController</BelongedController>

        <Type>Model</Type>

      </ElementDefinetion>

      <ElementDefinetion>

        <FullName> xxProj.GrpCallModel</FullName>

        <ShortName>GrpCallModel</ShortName>

        <AssemblyName> xxProj </AssemblyName>

        <BelongedController>GrpCallController</BelongedController>

        <Type>Model</Type>

      </ElementDefinetion>

    …………

     

    MVC模式下消息传递流程:
    下面是一个操作的消息传递(调用)流程:


     


     


     


     


     

    该操作的实际代码类似如下:

    主界面(ViewMainForm中:

    private void StartSchemaToolStripMenuItem_Click(object sender, EventArgs e)

    {

    this.SendMsg("MainForm.StartSchema", null);

    }

     

    MainForm的父类ViewElement中,SendMsg()方法实际上是通过一个被称为“发送代理SendProxy来发出消息:

    public ObjectDictionary SendMsg(string strMsgHeader, ObjectDictionary dicMsgContent)

    {

           return this.SendProxy.SendMsg(strMsgHeader,dicMsgContent);

    }

     

    在发送代理SendProxy中,调用MainForm所属的控制器的DistributeMsg()方法:

    public ObjectDictionary SendMsg(string strMsgHeader, ObjectDictionary dicMsgContent)

    {

    return this.Controller.DistributeMsg(strMsgHeader,dicMsgContent);

    }

     

    MainForm所属的控制器IndiController中,方法DistributeMsg()具有如下代码

    public override ObjectDictionary DistributeMsg(string strMsgHeader, ObjectDictionary dicMsgContent)

    {

    try

    {

    switch (strMsgHeader)

    {

    case "MainForm.StartSchema":

    this.ElementFactory.GetView("StartSchemaWizard1Form").ReceiveMsg("StartSchemaWizard1Form.StartSchem", dicMsgContent);

    return null;

    ……

    }

    }

    }

     

    其中ElementFactory.GetView("StartSchemaWizard1Form")利用C#中的反射机制返回类

    StartSchemaWizard1Form的一个对象(此时须用到上述的XML配置文件,以便在构造对象时传入其所属的控制器)。最终实现界面变化的代码则位于目标View(即StartSchemaWizard1Form)的ReceiveMsg()方法中,这样,一个操作最终完成。

     

    public override ObjectDictionary ReceiveMsg(string strMsgHeader, ObjectDictionary

    dicMsgContent)

    {

    switch (strMsgHeader)

    {

    case "StartSchemaWizard1Form.StartSchem":

    //界面变化

    ……

    break;

    ……

    }

    return null;

    }

     

     

    3.最后

    以上示例是曾经被实际应用过的MVC,写作的人恐怕也是参考了网上的例子,所以可能难免有些似曾相识。

     

    关于它的消息流程,你也可以很直白地将它理解为:将一个直接的函数调用拆分为两步,先调用控制器的相应方法,再经由控制器调用位于视图中的方法。(或者从视图到控制器到模型)

     

    所谓的消息,不过是些字符串,通过这些字符串来标识所要调用的目标。

     

    我在使用过程中遇到一个比较明显的问题,那就是调试,远不如分层架构那么直观,特别是当由控制器分发出来的是“异步消息(所谓异步即消息发出之后直接返回,不需等待目标方法完成)时,更加难以跟踪调试。当然,这可能跟架构作者和使用者的编程水平都有关系。

    菜鸟我对MVC的理解还是比较肤浅的,只是简单说说自己看到的和自己体会到的,大大们多多批评指正,万勿笑话。

     

  • 相关阅读:
    hive中使用正則表達式不当导致执行奇慢无比
    C/C++实现正负数四舍五入
    EEPlat的控制器概念
    由于好高骛远所以半途而废(张作作)
    新辰:关于“网络推广不能仅仅依靠网络”的详解
    SQL的事务回滚操作带案例分析
    怎样把引用的jar包和本项目一起导出成jar文件
    A星算法(Java实现)
    Hadoop之——HBASE结合MapReduce批量导入数据
    Spring MVC 数据验证——validate编码方式
  • 原文地址:https://www.cnblogs.com/morvenhuang/p/632307.html
Copyright © 2011-2022 走看看