谈.net开发人员应该熟悉的开发模式

  我们总会有这样一个经验:一个系统最不容易也最不应该变化的部分是领域逻辑,最容易变化也最应该变化的是数据的呈现方式。

  在java的各种应用中可以说是到处可见mvc,j2ee贯穿mvc的概念,android的开发方式也是类mvc的,mvc结构对于做过java应用的人而言简直就是司空见惯。而在.net这边,由于之前微软为大家提供的各种winform、asp.net项目典范(比如那个petshop series)将“三层”概念很好的灌输到了.net程序员的大脑中,许多.net开发者凡是做个东西都要搬出自己最拿手的IModel、IDAL这样的神器。

  其实mvc与所谓的“三层架构”是两个层次上的东西,前者是一种结构模式,而后者则是分层的角度去说。

  一件很奇怪的事情,许多人知道“三层”却不知道mvc,其实这要归结与.net的早期开发技术asp.net和winform这些page controller的典范让许多人对三层夸夸其谈却对mvc视而不见甚至一无所知。什么是page controller模式呢?搞.net的大多都用过winform和webform,这种xxxform用起来很直观,我们想要做一个程序,ok,最简单的方式就是拖拖拽拽几个控件,然后在一个叫code behind的东西里写这些UI事件的处理逻辑,加一大堆变量用于记录数据和状态,这样一个程序就能出炉。这种开发方式对于一些小软件系统的开发其实效率还是蛮高的,后来人们看到其弊端---一旦修改UI,事件处理就要跟着变,但是业务还是那个业务,凭什么要修改非UI的代码?于是有人提出“三层”,最朴素的理解就是将原本那堆事件处理里的code分成业务代码和数据库访问代码并转移到其它类中,做多了就把那坨UI叫做UI,那坨业务代码叫做BLL,那坨DAO叫做DAL。也就是这种架构:

  而对于j2ee的开发者来说熟悉的是下图。

  (说明:这两幅图copy自是daxnet文)

  MVC是什么

  MVC是一个很经典的结构,并且其又其思想衍生出很多变种比如MVP,MVVP。传统的MVC结构之一是这样的(拿主动型mvc来说):

  比如web开发(比如asp.net mvc或者是java的web开发方式),view就是纯web页面或者webservice,当提交一个表单/调用webservice或者ajax后会将数据提交给controller(当然期间可能会经过各种filterchain、listener这样的东西)controller调用相应的业务模块来处理这个请求,最终结果会更新View的显示。

  MVP

  对于非天然mvc的框架

  对于asp.net/winform而言,虽然可以通过改造让其支持mvc结构的开发(比如通过定制IHttpModule、IHttpHandler云云),但是在企业看来这些都算是邪门武功(因为这样会丧失xxxform在开发上的很多特性比如快速开发)。大多数使用的是mvp模式。什么是mvp呢?其实mvp是mvc的一个变种。因为用winform或者webform的话form始终是个阻碍mvc开发的问题。那么好,我们仍然使用designer和codebehind,其实一个架构设计的好坏是取决于人而不是具体的技术的,只要我们OO一时强page controller一样好用。

  在MVP模式中我们需要自己定制各个View(web页面或者窗体)对应的IView和IPresenter、IModel。IView要对IPresenter暴露操作UI、数据绑定的接口,IPresenter对IView要暴露当UI事件触发需要调用的接口,IPresenter根据IView传递过来的请求调用业务接口并根据结果操作UI。举个简单的例子,一个计算“x+y=?”的程序。如果我们这样定义IPresenter和IView

public interface IPresenter

{

IView View { get; set; }

void CalculateResult();

}

public interface IView

{

IPresenter Presenter { get; set; }

void ShowResult(string result);

int ValueOne { get; }

int ValueTwo { get; }

}

  IPresenter的实现如下(这里从简把IModel去掉了)

Presenternamespace ClientLibrary

{

    public class Presenter : IPresenter

    {

        private IView _view;

        public IView View

        {

            get

            {

                return _view;

            }

            set

            {

                _view = value;

                _view.Presenter = this;

            }

        }

private static readonly string RESULT_FORMATTER = "{0}+{1},the result is {2}";

        public void CalculateResult()

        {

            if (_view != null)

            {

                var result = string.Format(RESULT_FORMATTER, _view.ValueOne, _view.ValueTwo, _view.ValueOne + _view.ValueTwo);

                _view.ShowResult(result);

                this.A = 123;

            }

        }

        private int _a;

        public int A

        {

            set

            {

                A = value;

            }

        }

    }

}

View的实现如下(那silverlight为例,换成别的也行)

Main
Pagenamespace debug

{

    public partial class MainPage : UserControl, IView

    {

        public MainPage()

        {

            InitializeComponent();

        }

private IPresenter _presenter;

private void btn_Click(object sender, RoutedEventArgs e)

        {

            if (_presenter != null)

            {

                _presenter.CalculateResult();

            }

            #region hidden

            /*int total = 0;

            try

            {

                total = int.Parse(tb1.Text) + int.Parse(tb2.Text);

                MessageBox.Show("计算结果:" + total.ToString());

            }

            catch (Exception ex)

            {

                MessageBox.Show("出错啦" + ex.ToString());

            }

            finally

            {

                tb1.Text = string.Empty;

                tb2.Text = string.Empty;

            }*/

            #endregion

}

public IPresenter Presenter

        {

            get

            {

                return _presenter;

            }

            set

            {

                _presenter = value;

            }

        }

public void ShowResult(string result)

        {

            MessageBox.Show(result);

        }

public int ValueOne

        {

            get { return int.Parse(tb1.Text); }

        }

public int ValueTwo

        {

            get { return int.Parse(tb2.Text); }

        }

    }

}

  一个很简单的东西,看上去写成的要多些那么一坨东西,但是好处是显而易见的,就是更换view非常方便,根本不用去改你的IPresenter、Presenter和业务。一切都是接口调用而不依赖具体实现,这就是好处。

  你必须要懂的MVVM

  对于.NET平台的开发人员,托微软的福分我们拥有一种更为强大的模型---MVVM。这应该算是做WPF/Silverlight应用的人必懂的一种结构,WPF/silverlight天生支持数据绑定和命令绑定(不过sl在命令绑定上还比较弱),这就为我们使用MVVM创造了可能。

  View是什么呢,纯的View只有xaml或者附带必要的只与View本身相关逻辑代码。ViewModel,你可以把它理解为View具体呈现内容所依赖数据的一个抽象,在MVVM中View与ViewModel总会有一种绑定关系,一旦ViewModel中被绑定的数据发生改变View上的数据就会跟着变,相反也有可能,比如你的账号密码框内容发生变化,关联的ViewModel中的数据就会被框架自动通知到。

  在wpf/silverlight中,绑定是通过xaml语法来完成(虽然你可以选择用c#来写但不符合mvvm的宗旨),并且绑定双方的通知机制是有框架来完成,也就是说一个会xaml和blend的美工只需事先和coder商量下“咱们的xx和xx是在哪个ViewModel上叫XXX的属性的XXX属性……”问题之后就可以各干各的了。那么ViewModel怎么写,咋view中又怎么绑定到viewmodel呢?首先我们谈ViewModel。

  说道ViewModel你需要知道依赖属性和依赖对象的概念,这是wpf/silverlight的基础所以不多说。有两种方式写ViewModel。第一种是自己去实现INotifyPropertyChanged接口,并在属性变化时去调用NotifyPropertyChanged事件。

  为了方便我们定义一个ViewModelBase的抽象基类,然后让其他ViewModel继承这个基类。

ViewModelBasepublic abstract class ViewModelBase : System.ComponentModel.INotifyPropertyChanged, IDisposable 

    { 

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 

        protected void OnPropertyChanged(string propertyName) 

        { 

            if (PropertyChanged != null) 

            { 

                var arg = new System.ComponentModel.PropertyChangedEventArgs(propertyName); 

                PropertyChanged(this, arg); 

            } 

        } 

        public virtual void Dispose() 

        { 

           

        } 

    }DemoViewModelpublic class DemoViewModel : ViewModelBase

    {

        #region fields

        private string _propertyA;

        #endregion

        #region presentation properties

        public string PropertyA

        {

            get

            {

                return _propertyA;

            }

            set

            {

                if (_propertyA != value)

                {

                    _propertyA = value;

                    base.OnPropertyChanged("PropertyA");

                }

            }

        }

        #endregion

    }

  第二种是利用DependencyObject和DependencyProperty。

PeopleItemViewModelpublic class PeopleItemViewModel : DependencyObject, IPeopleItemViewModel

    {

        public PeopleItemViewModel()

        {

            

        }

        public static readonly DependencyProperty SimpleUserDataProperty = DependencyProperty.Register("SimpleUserData", typeof(SimpleUserData), typeof(PeopleItemViewModel));

        public static readonly DependencyProperty RelativeSimpleUserDataProperty = DependencyProperty.Register("RelativeSimpleUserData", typeof(ObservableCollection<SimpleUserData>), typeof(PeopleItemViewModel));

        public static readonly DependencyProperty AllSimpleUserDataPropert

时间: 2024-11-18 23:18:12

谈.net开发人员应该熟悉的开发模式的相关文章

15个值得开发人员关注的jQuery开发技巧和心得总结【经典收藏】_jquery

本文总结述了15个值得开发人员关注的jQuery开发技巧和心得.非常精辟实用!分享给大家供大家参考,具体如下: 在这篇文章中,我们将介绍15个让你的jQuery更加有效的技巧,大部分关于性能提升的,希望大家能够喜欢! 1. 尽量使用最新版本的jQuery类库 jQuery项目中使用了大量的创新.最好的方法来提高性能就是使用最新版本的jQuery.每一个新的版本都包含了优化的bug修复.对我们来说唯一要干的就是修改tag,何乐而不为呢? 我们也可以使用免费的CDN服务,例如, Google来存放j

开发人员工具 f12-ie9浏览器 开发人员工具 打不开

问题描述 ie9浏览器 开发人员工具 打不开 win7 64位系统ie9有两个,我把32位的那个删除,但是最近开发程序必须要用32位的ie浏览器,于是我卸载了ie9后又有重装了,结果32位的浏览器F12(开发者工具)打不开了,要怎么解决?

前端开发人员必须熟悉的10个CSS3属性

导读:随着Css3和html5的风靡,越来越多的前端人员开始学习Css3,今天的文章就是来说说前端应该掌握10个Css3属性. 对于Css3的新属性,你又了解多少呢?虽然大多数的css3属性在很多流行的浏览器中不支持,但是我们鼓励在前端开发中要学会并且运行这些css3属性,因为这是未来的趋势. 关键是首先确定你是否对各个浏览器之间的细微的差别有所了解,你能肯定的说IE显示的90度的角就不圆滑嘛?这取决于你的决定.但是要永远记住,网站设计不必看到所有浏览器的不同. 1. Border-radius

如何成为一名优秀物联网开发人员

物联网(IoT)行业正蓬勃发展.根据最近的Gartner报告,在2017年,全球使用的互联设备数量将达到84亿,超过全球人口总量. Gartner预测,到2020年,将会有超过208亿件物联网设备. 随着家庭互联.汽车互联和办公室互联变得越来越主流化,需要更多的开发人员来确保互联设备正常.安全地运行. IBM物联网开发人员生态系统主管Greg Gorman说:"'物联网开发人员'一词的含义很广泛,包括安全.网络.系统工程.云编程和硬件设备编程.开发人员应该在团队中灵活地扮演许多不同的角色.&qu

《iOS 9应用开发入门经典(第7版)》——第1章,第1.2节成为iOS开发人员

1.2 成为iOS开发人员 要成为iOS开发人员,并非只需坐下来编写程序即可.您需要一台较新的 Intel Macintosh台式机或笔记本电脑,它运行Mavericks或Yosemite,硬盘至少有8GB的可用空间.开发系统的屏幕空间越大,就越容易营造高效的工作空间.您甚至可将Xcode切换到全屏模式,将分散注意力的元素都隐藏起来.虽然如此,我在13英寸MacBook Air中开发时也相当舒服,因此并非一定要使用多显示器系统. 假设您有运行Yosemite或El Capitan的Mac,还需要

《iOS 8应用开发入门经典(第6版)》——第1章,第1.2节成为iOS开发人员

1.2 成为iOS开发人员iOS 8应用开发入门经典(第6版)要成为iOS开发人员,并非只需坐下来编写程序即可.您需要一台较新的 Intel Macintosh台式机或笔记本电脑,它运行Mavericks或Yosemite,硬盘至少有6GB的可用空间.开发系统的屏幕空间越大,就越容易营造高效的工作空间.您甚至可将Xcode切换到全屏模式,将分散注意力的元素都隐藏起来.虽然如此,我在13英寸MacBook Air中开发时也相当舒服,因此并非一定要使用多显示器系统. 假设您有Mac,还需要什么呢?好

为什么越简单的技术对于开发人员越难

简单 != 容易从Amazon Web服务到 AngularJS之类的web框架,便利性 驱动 着世界上最好的技术.但是,更加快速地.变得有效率的"便利性",经常伴随着一个隐藏的价格标签:为了变得真正有效率,你将不得不花些功夫. 伟大的技术经常貌似简单,新手们直觉上不需要太多努力就可以"学习".当人们认为他们已经掌握了这门技术.而他们真正做的所有工作相当于是一个"hello world"程序的等价物时,问题就出现了.在你归咎于这个工具之前,你往往

谷歌Android策略引发内讧 开发人员可能倒戈

8月13日消息,据国外媒体报道,谷歌给人们留下的印象就是从来不会做错事情,但在Android平台策略上,这一美好印象可能就要被打破. 在开源移动平台Android即将公开发布之际,谷歌的一些行为却可能永久破坏其与开发人员之间的关系,其中包括限制开发人员获得核心开发工具.即使不会遭到开发人员的倒戈,那么也会让他们感到失望和希望破灭. 据第三方Android博客网站AndroidGuys预计,Android开发社区大约拥有2000名开发人员.其中很多开发人员表示,他们将转向其他移动平台. Andro

谷歌Android策略引发内讧 开发人员倒戈

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 8月13日消息,据国外媒体报道,谷歌给人们留下的印象就是从来不会做错事情,但在Android平台策略上,这一美好印象可能就要被打破. 在开源移动平台Android即将公开发布之际,谷歌的一些行为却可能永久破坏其与开发人员之间的关系,其中包括限制开发人员获得核心开发工具.即使不会遭到开发人员的倒戈,那么也会让他们感到失望和希望破灭. 据第三方A