一、前言

最近做CAD插件相关的工作,用到了一些模式,解决对应场景的问题。 比如插件的运行实例上使用Singleton、实例内部使用了MVC(Strategy and Observer )。

针对CAD插件,插件可以在CAD运行过程中多次打开关闭,数据状态需要保持一致,数据联动,及多种UI布局模式。

1、Singleton 维持一个全局唯一实例,使得插件运行变得有“状态” 、提升插件的打开速度。

2、MVC 对程序结构进行解耦,方便不同UI进行数据互通、复用使用多种UI布局模式。

3、在这里本文主要针对MVC进行回顾。

代码链接:https://github.com/Shawn-china/MVCDemo.git

二、场景与模式

模式很多,场景各不同通常一个模式都对应一个特定场景,所以也就没有什么万能模式解决所有问题。从"Gang of Four" 总结23种设计模式之后,又不断有新的模式被总结出来。

比如:创建型模式中Singleton 维护一个全局唯一实例、Factory负责创建实例;行为型模式解决一些运行时问题;结构型模式适用模板类问题。

使用面向对象开一个应用程序除了满足功能需求,其次还要达到OO目标。 代码层面可读、高内聚低耦合、复用易扩展维护等。

实现目标二可通过多种途径:遵循代码规范、使用模式、面向抽象、面向接口、使用组合等具体的方法。

一些常见的开发框架中也可以看到很多模式的影子, Vue.js中双向绑定使用观察者模式实现,Qt中Model/View 模式简化了UI和数据的“交互”,一些带发布订阅机制的第三方软件。

三、MVC

MVC是挪威计算机科学家:Trygve Mikkjel Heyerdahl Reenskaug,在1979年为GUI软件设计制定的模式。参考维基百科:https://en.wikipedia.org/wiki/Trygve_Reenskaug

MVC有三种类型的“对象”。

Model 应用程序数据,

View  应用程序UI,可以有多种体现形式如:winform、wpf、控制台、web页面等,

Controller定义了View对输入的处理方式。

当Model数据更改时,它将更新View。一个模型可以对应多个视图。

如下图示:

四、UML 类图

MVC有很多具体形式,可以view 先行也可以controller先行。在这里使用图一UML所描述的实现方式。注:本质上其实为 Observer 与 Strategy 复合模式。

                       图一

五、Code show

1、Model 实现一个数据监听 Observer,对数据数据对象进行监听,当数据变动可以通知订阅者。

    public interface IModel
{
ArrayList DataObservers { get; set; } void RegisterObserver(IDataObserver concreteObserver, string key); void UnregisterObserver(IDataObserver concreteObserver); /// <summary>
///
/// </summary>
/// <param name="baseObject">Base class containing an Id field and a Name field</param>
/// <param name="key"></param>
void GetData(BaseObject baseObject, string key);
}

IModel

    public class ConcreteModel : IModel
{
public ArrayList DataObservers { get; set; } = new ArrayList(); public void RegisterObserver(IDataObserver concreteObserver, string key)
{
if (!this.DataObservers.Contains(concreteObserver))
{
this.DataObservers.Add(concreteObserver);
}
} public void UnregisterObserver(IDataObserver concreteObserver)
{
if (this.DataObservers.Contains(concreteObserver))
{
this.DataObservers.Remove(concreteObserver);
}
} public void GetData(BaseObject baseObject, string key)
{
this.Notity(baseObject, key);
} private void Notity(BaseObject baseObject, string key)
{
foreach (object item in this.DataObservers)
{
if (((IDataObserver)item).ObserverKeys.Contains(key))
{
((IDataObserver)item).Update(baseObject);
}
}
}
}

ConcreteModel

2、view 包含一个Model 一个Controller  ,实现IDataObserver接口 。示例包含三个view : 1、ComboBox 2、TreeView 3、DataGridView

IDataObserver 数据观察者

    public interface IDataObserver
{
List<string> ObserverKeys { get; set; } string SubscriptionKey { get; set; } void Update(object data);
}

IDataObserver

BaseRequest 作为所有view类的基类,包含一个Model 一个Controller

    public class BaseRequest
{
public static IModel ConcreteModel;
public static IController ConcreteController; public BaseRequest()
{
ConcreteModel = ConcreteModel ?? new ConcreteModel();
ConcreteController = ConcreteController ?? new ConcreteController(ConcreteModel);
} public BaseRequest(IModel concreteModel, IController concreteController)
{
ConcreteModel = ConcreteModel ?? concreteModel;
ConcreteController = ConcreteController ?? concreteController;
}
}

BaseRequest

ComboBox ,被TreeView 和 DataGridView 观察 。

    public class ConcreteComboxRequest : BaseRequest, IDataObserver
{
private readonly ComboBox _comboBox; public ConcreteComboxRequest(ComboBox comboBox)
{
this._comboBox = comboBox;
this.IntializeView();
} public List<string> ObserverKeys { get; set; } public string SubscriptionKey { get; set; } = $"{nameof(ConcreteComboxRequest)}"; public void Update(object data)
{
this._comboBox.DataSource = DataContainer.Schools;
} private void IntializeView()
{
this._comboBox.DisplayMember = "Name";
this._comboBox.ValueMember = "Id";
this._comboBox.SelectedIndexChanged += this.cmb_SelectedValueChanged;
} private void cmb_SelectedValueChanged(object sender, EventArgs e)
{
BaseObject baseObject = (BaseObject)this._comboBox.SelectedItem;
ConcreteController.GetDatas(baseObject, this.SubscriptionKey);
}
}

ConcreteComboxRequest

TreeView,注册到Model监听Observer中,观察ComboBox。 同时被DataGridView 观察

public class ConcreteTreeviewRequest : BaseRequest, IDataObserver
{
private readonly TreeView _treeView; public ConcreteTreeviewRequest(TreeView treeView)
{
this._treeView = treeView;
this.IntializeView();
} public List<string> ObserverKeys { get; set; } = new List<string> { $"{nameof(ConcreteComboxRequest)}" }; public string SubscriptionKey { get; set; } = $"{nameof(ConcreteTreeviewRequest)}"; public void Update(object data)
{
BaseObject baseObject = (BaseObject)data;
this.InitializeTreeView(baseObject);
} private void IntializeView()
{
foreach (string observerKey in this.ObserverKeys)
{
ConcreteModel.RegisterObserver(this, observerKey);
} this._treeView.AfterSelect += this.treeView_SelectedValue;
} private void InitializeTreeView(BaseObject baseObject)
{
this._treeView.Nodes.Clear();
List<Grade> grades = Grade.GetList(baseObject); foreach (Grade item in grades)
{
this.CreateTreeNode(null, item);
}
} private void treeView_SelectedValue(object sender, TreeViewEventArgs e)
{
TreeNode currentNode = this._treeView.SelectedNode; BaseObject baseObject = (BaseObject)currentNode.Tag; ConcreteController.GetDatas(baseObject, this.SubscriptionKey);
} private TreeNode CreateTreeNode(TreeNode parentNode, BaseObject concreteData)
{
TreeNode treeNode = new TreeNode
{
Tag = concreteData,
Name = concreteData.Id,
Text = concreteData.Name
}; if (parentNode == null)
{
this._treeView.Nodes.Add(treeNode);
}
else
{
parentNode.Nodes.Add(treeNode);
} return treeNode;
}
}

ConcreteTreeviewRequest

DataGridView,,注册到Model监听Observer中,观察ComboBox、TreeView 。

public class ConcreteDataGridViewRequest : BaseRequest, IDataObserver
{
private readonly DataGridView _dataGridView; public ConcreteDataGridViewRequest(DataGridView dataGridView)
{
this._dataGridView = dataGridView;
this.IntializeView();
} public List<string> ObserverKeys { get; set; } = new List<string>
{
$"{nameof(ConcreteTreeviewRequest)}",
$"{nameof(ConcreteComboxRequest)}"
}; public string SubscriptionKey { get; set; } = $"{nameof(ConcreteDataGridViewRequest)}"; public void Update(object data)
{
BaseObject baseObject = (BaseObject)data;
this.InitializeDataGridView(baseObject);
} private void InitializeDataGridView(BaseObject baseObject)
{
this._dataGridView.Columns.Clear();
List<Student> students = Student.GetList(baseObject); this._dataGridView.DataSource = students;
} private void IntializeView()
{
foreach (string observerKey in this.ObserverKeys)
{
ConcreteModel.RegisterObserver(this, observerKey);
} this._dataGridView.SelectionChanged += this.dataGridView_SelectionChanged;
} private void dataGridView_SelectionChanged(object sender, EventArgs e)
{
// Do some business logic
}
}

ConcreteDataGridViewRequest

3、Controller 包含一个 Model ,当某一view “主题”变化时,调用Model 通知对应的订阅对象。

public interface IController { void GetDatas(BaseObject baseObject, string subscriberKey); }

    public class ConcreteController : IController
{
private readonly IModel _model; public ConcreteController(IModel model)
{
this._model = model;
} public void GetDatas(BaseObject baseObject, string subscriberKey)
{
this._model.GetData(baseObject, subscriberKey);
}
}

ConcreteController

浅析MVC Pattern的更多相关文章

  1. 浅析 MVC Pattern

    一.前言 最近做CAD插件相关的工作,用到了一些模式,解决对应场景的问题. 比如插件的运行实例上使用Singleton.实例内部使用了MVC(Strategy and Observer ). 针对CA ...

  2. 浅析MVC模式与三层架构的区别

    浅析MVC模式与三层架构的区别 三层架构和MVC是有明显区别的,MVC应该是表现模式(三个加起来以后才是三层架构中的UI层).三层架构(3-tier application) 通常意义上的三层架构就是 ...

  3. ASP.NET MVC:mvc pattern

    There are three pieces to the MVC pattern: The model—The domain that your software is built around. ...

  4. 从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler

    熟悉WebForm开发的朋友一定都知道,Page类必须实现一个接口,就是IHttpHandler.HttpHandler是一个HTTP请求的真正处理中心,在HttpHandler容器中,ASP.NET ...

  5. 浅析MVC模式与三层架构的区别01

    三层架构和MVC是有明显区别的,MVC应该是展现模式(三个加起来以后才是三层架构中的UI层)三层架构(3-tier application) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI ...

  6. 【转】从源码浅析MVC的MvcRouteHandler、MvcHandler和MvcHttpHandler

    原文:http://www.cnblogs.com/jeffwongishandsome/archive/2012/01/08/2316521.html 熟悉WebForm开发的朋友一定都知道,Pag ...

  7. .net mvc笔记1_ The MVC Pattern

    1.controller中的每一个public method被称为action method,意味着你可以从web上通过URL来调用它,以此来执行一个action. 2.当我们从action meth ...

  8. 浅析MVC和说媒的过程

    什么是MVC? MVC 全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面 显 ...

  9. Pro Aspnet MVC 4读书笔记(2) - The MVC Pattern

    Listing 3-1. The C# Auction Domain Model using System; using System.Collections.Generic; using Syste ...

随机推荐

  1. List集合的排序

    最近在写需求时,将某张表中的短信信息拿出,sql写完后,取出来后的结构是List<Map>,在进行到某一步时需要将这个List<Map>进行逆序排序, 当时第一想法便是写一个f ...

  2. Erlcron分析学习

    介绍 Erlcron实现类似Linux下面的cron的计划任务. 源码下载地址:https://github.com/erlware/erlcron 原理 Erlcron进程监控树 ecrn_cron ...

  3. Docker下Jedis体验

    jedis是redis的java版本的客户端实现,本文通过一些web请求&响应的实例展示了jedis的基本用法: 开始编码前我们先把环境准备好,总共两个server,对应两个docker容器: ...

  4. 用Python分析2000款避孕套,得出这些有趣的结论

    到现在为止,我们的淘宝教程已经写到了第四篇,前三篇分别是: 第一篇:Python模拟登录淘宝,详细讲解如何使用requests库登录淘宝pc端. 第二篇:淘宝自动登录2.0,新增Cookies序列化, ...

  5. 解决在Filter中读取Request中的流后,后续controller或restful接口中无法获取流的问题

    首先我们来描述一下在开发中遇到的问题,场景如下: 比如我们要拦截所有请求,获取请求中的某个参数,进行相应的逻辑处理:比如我要获取所有请求中的公共参数 token,clientVersion等等:这个时 ...

  6. 作为IT面试官,我如何考核计算机专业毕业生?作为培训班老师,我又如何提升他们?

    我最近几年一直在做技术面试官,除了面试有一定工作经验的社会人员外,有时还会面试在校实习生和刚毕业的大学生.同时,我也在学校里做过兼职讲师,上些政府补贴课程(这些课程有补贴,学生不用出钱),所以我会在不 ...

  7. OPC-System.Runtime.InteropServices.COMException:“Error HRESULT E_FAIL has been returned from a call to a COM component.”

    Error HRESULT E_FAIL has been returned from a call to a COM component的错误提示,还是因为OPC配置,这次是红框中标签定义错误,应该 ...

  8. charles 设置为chrome代理

    本文参考:charles 设置为chrome代理 将charles设置为chrome的代理 需要注意的是,Chrome 和 Firefox 浏览器并不一定使用的就是本机,可能是一些代理工具,而 Cha ...

  9. DirectX12 3D 游戏开发与实战第一章内容

    DirectX12 3D 第一章内容 学习目标 1.学习向量在几何学和数学中的表示方法 2.了解向量的运算定义以及它在几何学中的应用 3.熟悉DirectXMath库中与向量有关的类和方法 1.1 向 ...

  10. Java连载34-对象的内存分析、对象之间建立关系

    一.内存分析 代码:引用可以是局部变量也可以是成员变量 public class Test1{ public static void main(String[] args){ User u = new ...