MVP之V和P的交互
三者之间的关系
在MVP初探里简单的描述了V和P之间是如何交互的。
无论是PV还是SC,M\V\P这三者之间的关系并没有发生改变,V只是前端的客户代理承现展显数据,P是如何处理客户交互行为的决策者。
数据是P主动“推”给V的,而V只向P发送用户通知,都是单向的;所以在IView中被Presenter调用的方法应该都是没有返回值的。可以通过调用IView中的方法,也可以通过事件注册的方式来实现P/V之间的交互。
那么,在PV模式下View是被动的,而P则控制着对V请求的处理;view仅将用户的(事件)请求提交到P,它并不参与对用户请求的处理,如果在这个过程中P要V参与(如:显示实时的数据等)也是P将要展现的数据PUSH到V,对于处理的结果的呈现也是同样的处理方式。
而P在此过程中的角色是一个决策者,它决定如何处理V提交过来的用户请求,如何去实现业务逻辑和调用Model。
如何维护三者的关系
View仅是传递用户请求和对数据的呈现;Presenter是事件的的决策者;Model业务逻辑执行者。
在PV中三者的关系使用的uView可以直接调用Presenter,这样就会使用的在开发过程中将Presenter作为View和Model之间的一种代理(Proxy)而不是Presenter.
那么我们就可以通过事件订阅机制来解决这个问题。
编程模型的实现
首先,要让View不能访问到Presenter,我们可以通过事件订阅机制;为所有的Presenter创建基类Presenter<IView>,泛型类型IView表示具体View实现的接口。表示View的同名只读属性在构造函数中赋值,赋值完成之后调用调用虚方法OnViewSet,使得对具体的Presenter可以重写该方法进行对View进行事件注册工作。
namespace Handwe.Demo.MVP
{
public class Presenter<IView>
{
public IView View { get; set; } public Presenter(IView view){
this.View = view;
this.OnViewSet();
} protected virtual void OnViewSet()
{ }
}
}
其次,Presenter是通过接口的方式与View进行交互的。有时候我们要通过这个接口访问Form的一些属性、方法和事件,需要将相应的成员定义在接口上面,可能会有很多,添加的删减等。那么,我们可以将这些成员定义在一个接口中,具体View的接口继承该接口就可以了。在这里,我们相当是为所有的View接口创建了“基接口”。如下:
namespace Handwe.Demo.MVP
{
public interface IViewBase
{
event EventHandler Load;
event EventHandler Closed;
event CancelEventHandler Closing; string ResultText
{
get;set;
} }
}
同时,也要创建所有的View创建基类ViewBase,做必要的初始化工作,如加载基础数据等:
namespace Handwe.Demo.MVP
{
public class ViewBase : Form
{
public ViewBase()
{
this.CreatePresenter();
} protected virtual object CreatePresenter()
{
if (LicenseManager.CurrentContext.UsageMode == LicenseUsageMode.Designtime)
{
return null;
}
else
{
throw new NotImplementedException(string.Format("{0} must override the CreatedPresenter method.", this.GetType().FullName));
}
}
}
}
在ViewBase中调用CreatedPresenter(),它的实现在具体的每个View中也就是实现Presenter和View对应;
public partial class CalculatorView : ViewBase, ICalculatorView
...
protected override object CreatePresenter()
{
return new CalculatePresenter(this);
} ...
}
实例的实现:
那边现在可以定义View的接口ICalculatorView,在这里定义了一个事件Calculating,也就是点击btnCalculate触发,还要定义三个方法,DisplayResult(int result)、DisplayMsg(stirng msg)、还有一个是Clear();具体什么用途看名称就知道了,如下:
namespace Handwe.Demo.UnityInMVP
{
public interface ICalculatorView : IViewBase
{
event EventHandler<CalculateEventArgs> Calculating; void DisplayResult(int result); void DisplayMsg(string msg); void Clear();
}
}
这里有一个CalculateEventArgs,它是自定义的事件参数类型:
namespace Handwe.Demo.UnityInMVP
{
public class CalculateEventArgs : EventArgs
{
public string OperationNum1 { get; set; } public string OperationNum2 { get; set; }
}
}
很简单只定义了两个属性;
接着来实现CalculatorView,代码如下:
namespace Handwe.Demo.UnityInMVP
{
public partial class CalculatorView : ViewBase, ICalculatorView
{
public CalculatorView()
{
InitializeComponent();
} public string ResultText
{
get { return this.labResult.Text; } set{this.labResult.Text = value;}
} protected override object CreatePresenter()
{
return new CalculatorPresenter();
} #region ICalculateView Members
public event EventHandler<CalculateEventArgs> Calculating; public void DisplayResult(int result)
{
this.textBoxResult.Text = result.ToString();
} public void Clear()
{
this.textBoxOp1.Text = string.Empty;
this.textBoxOp2.Text = string.Empty; this.DisplayMsg(string.Empty);
} public void DisplayMsg(string msg)
{
this.labDisplayMsg.Text = msg;
}
#endregion private void btnCalculate_Click(object sender, EventArgs e)
{
string op1 = this.textBoxOp1.Text.Trim();
string op2 = this.textBoxOp2.Text.Trim();
this.OnCalculating(op1, op2);
} private void btnClear_Click(object sender, EventArgs e)
{
} private void btnCheck_Click(object sender, EventArgs e)
{
} protected virtual void OnCalculating(string op1, string op2)
{
if (null != this.Calculating)
{
this.Calculating(this, new CalculateEventArgs { OperationNum1 = op1, OperationNum2 = op2 });
}
}
}
}
然后我们实现事件的订阅者,这里就是CalculatePresenter:
namespace Handwe.Demo.UnityInMVP
{
public class CalculatePresenter : Presenter<ICalculatorView>
{
public CalculatePresenter(ICalculatorView view):base(view)
{
this.Calculate = new Calculate();
} 10
public Calculate Calculate
{
get;
set;
} protected override void OnViewSet()
{
this.View.Load += (sender, args) =>
{ this.View.Clear();
}; this.View.Calculating += (sender, args) =>
{
int op1, op2;
if (!int.TryParse(args.OperationNum1, out op1))
{
this.View.DisplayMsg(string.Format("{0} type invalid.", args.OperationNum1));
return;
} if (!int.TryParse(args.OperationNum2, out op2))
{
this.View.DisplayMsg(string.Format("{0} type invalid.", args.OperationNum1));
return;
}
int result = this.Calculator.Divide(op1, op2); this.View.DisplayResult(result); this.View.Clear();
this.View.DisplayMsg("please type operation numbers.");
};
}
}
}
至此,Calculator演示实例已基本完成了,下篇将会在这个实例的基础上引入Unity、PIAB、Exception Handling,实现对Calculate的解耦和异常处理。《Unity、PIAB、Exception Handling引入MVP》
http://www.cnblogs.com/coble/p/5646717.html
MVP之V和P的交互的更多相关文章
- Exception Handling引入MVP
异常处理(Exception Handling)是所有系统的最基本的基础操作之一,其它的比如日志(Logging).审核(Auditing).缓存(Caching).事务处理(Transaction) ...
- MVP初探
什么是MVP MVP是一种UI的架构模式,是MVC的一种变体,适用于基于事件驱动的应用框架.MVP中的M和V分别对应了MVC中的Model和View,而P代替了Controller,而它更多地体现在了 ...
- Unity、Exception Handling引入MVP
什么是MVP?在“MVP初探”里就有讲过了,就是一种UI的架构模式. 简单的描述一下Unity和Exception Handling Application Block: Unity是一个轻量级的可扩 ...
- mvc架构和mvp架构
mvc,mvp其实是复合模式,是多个设计模式的组合:将多个模式结合起来形成一个框架,已解决一般性问题. mvc: 既然mvc是复合模式,那么是由哪些设计模式组合的呢? 观察者设计模式:view和con ...
- 如何使用MVP+Dagger2+RxJava+Retrofit开发(1)
概述 在2016年5,6月份开始在知乎上看到开发方法,那时候记得是看mvc,mvp,mvvm这三种开发模式区别,后面进一步了解到google在github上开源了使用这3种模式进行Android开发的 ...
- MVC和MVP设计模式
参考博客http://www.cnblogs.com/end/archive/2011/06/02/2068512.html ####MVC模式M:model 模型V:view 视图C:control ...
- 架构 : 三层架构、MVC、MVP、MVVM
1. 三层架构 将整个业务应用划分为:界面层(User Interface layer, UIL).业务逻辑层(Business Logic Layer, BLL).数据访问层(Data acce ...
- Android中的MVP架构初探
说来羞愧,MVP的架构模式已经在Android领域出现一两年了.可是到今天自己才開始Android领域中的MVP架构征程. 闲话不多说,開始吧. 一.架构演变概述 我记得我找第一份工作时,面试官问我& ...
- mvp设计模式
一.设计模式的简单介绍 MVP的 V 层是由UIViewController 和UIView 共同组成view 将委托presenter 对它自己的操作,(简单来说就是presenter发命令来控制v ...
随机推荐
- 在网页布局中合理使用inline formating context(IFC)
引子:给大家出一个小小的考题,如何使用css来实现类似下面的在指定区域内,内容自适应的垂直居中.
- 关于jquery中用函数来设置css样式
关于jquery中用函数来设置css样式 2016-12-21 23:27:55 1.jquery语法 $(selector).css(name,function(index,value)) name ...
- 如何基于OM模型使用C#在程序中给SharePoint的BCS外部数据类型的字段赋值
概述: 外部内容类型和数据,SharePoint从2010这个版本开始就对BCS提供非常强大的支持,点点鼠标就可以取代以前直接编辑XML的方式来设置SharePoint到SQL数据库的连接.非常方便地 ...
- SharePoint 2007 Full Text Searching PowerShell and CS file content with SharePoint Search
1. Ensure your site or shared folder in one Content Source. 2. Add file types. 3. The second step in ...
- iOS之两个ImageView实现图片滚动
原创作者:codingZero 导语 在不少项目中,都会有图片轮播这个功能,现在网上关于图片轮播的框架层出不穷,千奇百怪,笔者根据自己的思路,用两个imageView也实现了图片轮播,这里说说笔者的主 ...
- Android Support Library介绍
v4 Support Library 这个库是为Android 1.6(API版本为4)及以上的版本设计的,它包含大部分高版本中有而低版本中没有的API,包括application component ...
- RecyclerView-------MainActivity代码
package com.example.administrator.recyclerview; import android.support.v7.app.AppCompatActivity; imp ...
- Linux查看系统开机时间
有时候需要查看Linux系统运行了多久时间,此时需要知道上次开机启动时间: 有时候由于断电或供电故障突然停机,需要查看Linux开机时间/重启时间: 下面总结一些查看Linux开机关机时间的方法(非 ...
- J2EE基础之JavaBean
J2EE基础之JavaBean 1.什么是JavaBean? JavaBean本质上来说就是一个Java类,它通过封装属性和方法成为具有独立功能.可重复使用的,并可以与其他控件通信的组件对象.通过在J ...
- JSP连接MySQL数据库问题
之前写了一大段,还说了一下具体JDBC连接数据库API的具体包的基本知识,哪知道自己手残不小心按了删除按钮.结果去看自动保存记录时,就只剩下下面这段了.好吧,其实最主要最核心的也就是下面这点了.具体如 ...