一、前言

最近做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. PyQt(Python+Qt)学习随笔:formLayout的layoutFormAlignment 属性

    一.引言 Qt Designer的表单布局(formLayout)中,layoutFormAlignment 用于控制表单布局中所有子部件在布局框内的对齐方式(与layoutLabelAlignmen ...

  2. 常见SQL注入点判断

    sql注入手工检测 SQL注入手工检测 1基本检测 数字型 字符型 搜索型 POST注入 布尔盲注 报错注入 堆叠注入 判断是什么数据库 2绕过技巧 大小写 替换关键字 使用编码 注释和符号 等价函数 ...

  3. Hive基本原理及配置Mysql作为Hive的默认数据库

    Hive是什么? Hive是基于Hadoop之上的数据仓库: Hive是一种可以存储.查询.分析存储在hadoop中的大规模数据 Hive定义了简单的类SQL查询语言,成为HQL,它允许熟悉SQL的用 ...

  4. HTML基础之标签

    HTML初识 HTML(Hpyer Text Markup Language的缩写)译为"超文本标签语言",用来描述网页的一种语言.所谓超文本,因为它可以加入图片.声音.动画.多媒 ...

  5. Java并发编程的艺术(三)——synchronized

    什么是synchronized synchronized可以保证某个代码块或者方法被一个线程占有,保证了一个线程的可先性.java 1.6之前是重量级锁,在1.6进行了各种优化,就不那么重了,并引入了 ...

  6. 使用OpenSSL自建一个HTTPS服务

    1. 理论知识 1.1 什么是https 传统的 HTTP 协议以明文方式进行通信,不提供任何方式的数据加密,很容易被中间攻击者破解通信内容或者伪装成服务器与客户端通信,在安全性上存在很大问题. HT ...

  7. 【Jmeter 压测MySql连接问题】

    JDBC Request :Cannot load JDBC driver class 'com.mysql.jdbc.Driver'解决办法   在Jmeter中run JDBC Request时, ...

  8. PDCA

    Plan(规划) Do(执行) Check(验证) Adjust(调整)

  9. 一文搞懂I/O多路复用机及其技术

    前言 ​ 高性能是每个程序员的追求,无论写一行代码还是做一个系统,都希望能够达到高性能的效果.高性能架构设计主要集中在两方面: 尽量提升单服务器的性能,将单服务器的性能发挥到极致 如果单服务器无法支撑 ...

  10. 未雨绸缪,数据保护之NBU介质备份

    摘要:华为GaussDB目前已支持NBU介质的备份与恢复,本文主要描述了华为GaussDB数据库和NetBackup对接进行备份.恢复的配置方法与性能调优方法. 一.简介 企业要想避开自然灾难和站点中 ...