海妖 发表于 2015-1-16 22:32:36

ASP.NET教程之用Visual C#完成MVC形式的扼要办法

捆绑编译器。用户不需要受制于厂家,自己就能将程序在新平台上编译运行。除了牛B轰轰的linux,估计也没有系统捆绑c/c++的编译器,而且许多新平台都无法支持复杂的c/c++编译器在上面直接运行。visual  在我们的开辟项目中利用MVC(Model-View-Control)形式的好处是,能够完整下降营业层和使用暗示层的互相影响。别的,我们会有完整自力的工具来操纵暗示层。MVC在我们项目中供应的这类工具和层之间的自力,将使我们的保护变得更复杂使我们的代码重用变得很简单(上面你将看到)。

  作为一样平常的习气,我们晓得我们但愿坚持最低的工具间的依附,如许变更可以很简单的失掉满意,并且我们能够反复利用我们辛辛劳苦写的代码。为了到达这个目标我们将遵守一样平常的准绳“对接口编成,而不是对类”来利用MVC形式。

  我们的任务,假如我们选择承受它...

  我们被委任构建一个ACME2000SportsCar项目,我们的义务是做一个复杂的Windows画面来显现汽车的偏向和速率,使终端用户可以改动偏向,减速或是加速。固然将会有局限的扩大。

  在ACME已有了传言,假如我们的项目乐成,我们终极还要为ACME2PickupTruck和ACME1Tricycle开辟一个类似的接口。作为开辟职员,我们也晓得ACME办理团队终极将问“如许是很棒的,我们可以在我们的intranet上看到它?”一切的这些出现在脑海中,我们想托付一个产物,使它可以简单的晋级以便可以包管未来我们可以有饭吃。

  以是,同时我们决意“这是利用MVC的一个尽好情况”

  我们的构架提要

  如今我们晓得我们要利用MVC,我们必要指出它的实质。经由过程我们的实验得出MVC的三个部分:Model,Control和View。在我们的体系中,Model就是我们的汽车,View就是我们的画面,Control将这两个部分接洽起来。

  为了改动Model(我们的ACME2000sportscar),我们必要利用Control。我们的Control将会发生给Model(我们的ACME2000sportscar)的哀求,和更新View,View就是我们的画面(UI)。

  这看起来很复杂,可是这里发生了第一个要办理的成绩:当终端用户想做一个对ACME2000sportscar一个改动将会产生甚么,好比说减速或是转向?他们将经由过程View(ourwindowsform)用Control来提出一个变更的请求。

  如今我们就剩下一个未办理成绩了。假如View没有需要的信息来显现Model的形态怎样办?我们必要再在我们的图中到场一个箭头:View将能请求Model的形态以便失掉它要显现的相干形态信息。

  最初,我们的终极用户(司机)将会和我们的ACMEVehicleControl体系经由过程View来交互。假如他们想收回一个改动体系的请求,好比进步一点减速度,请求将会从View入手下手收回由Control处置。

  Control将会向Model请求改动并将需要的变更反应在View上。好比,假如一个悍戾的司机对ACME2000SportsCar做了一个"floorit"请求,而如今行驶的太快不克不及转向,那末Control将会回绝这个请求并在View中关照,如许就避免了在交通拥堵是产生凄惨的连环相撞。

  Model(theACME2000SportsCar)将关照View它的速率已进步,而View也将做得当的更新。

  综上,这就是我们将构建的提要:

  入手下手

  作为老是想的远一点的开辟职员,我们想让我们的体系有一个久长而且优秀的性命周期。这就是说可以进大概的筹办好满意ACME的良多变更。为了做到这一点,我们晓得要遵守两条准绳...“包管你的类低耦合”,要到达这个方针,还要“对接口编程”。

  以是我们要做三个接口(正如你所推测,一个Model接口,一个View接口,一个Control接口)。

  经由良多查询拜访研讨,和与ACME人的吃力征询,我们失掉了良多有关具体计划的信息。我们想断定我们能够设置的最年夜速率在行进,前进和转弯中。我们也必要可以减速,加速,左转和右转。我们的仪表盘必需显现以后的速率和偏向。

  完成一切这些需求长短常刻薄的,可是我们确信我们可以做到...

  起首,我们思索一下基础的项目。我们必要一些器材来暗示偏向和动弹哀求。我们做了两个列举范例:AbsoluteDirection和RelativeDirection。

publicenumAbsoluteDirection
{
 North=0,East,South,West
}
publicenumRelativeDirection
{
 Right,Left,Back
}

  上面来办理Control接口。我们晓得Control必要将哀求传送给Model,这些哀求包含:Accelerate,Decelerate,和Turn。我们创建一个IVehicleControl接口,并到场得当的办法。

publicinterfaceIVehicleControl
{
 voidAccelerate(intparamAmount);
 voidDecelerate(intparamAmount);
 voidTurn(RelativeDirectionparamDirection);
}

  如今我们来收拾Model接口。我们必要晓得汽车的名字,速率,最年夜速率,最年夜发展速率,最年夜转弯速率和偏向。我们也必要减速,加速,转弯的函数。

publicinterfaceIVehicleModel
{
 stringName{get;set;}
 intSpeed{get;set;}
 intMaxSpeed{get;}
 intMaxTurnSpeed{get;}
 intMaxReverseSpeed{get;}
 AbsoluteDirectionDirection{get;set;}
 voidTurn(RelativeDirectionparamDirection);
 voidAccelerate(intparamAmount);
 voidDecelerate(intparamAmount);
}

  最初,我们来收拾View接口。我们晓得View必要表露出Control的一些性能,好比同意或克制减速,加速和转弯请求。

publicinterfaceIVehicleView
{
 voidDisableAcceleration();
 voidEnableAcceleration();
 voidDisableDeceleration();
 voidEnableDeceleration();
 voidDisableTurning();
 voidEnableTurning();
 }

  如今我们必要做一些微调使我们的这些接口可以相互感化。起首,任何一个Control都必要晓得它的View和Model,以是在我们的IvehicleControl接口中到场两个函数:"SetModel"和"SetView":

publicinterfaceIVehicleControl
{
 voidRequestAccelerate(intparamAmount);
 voidRequestDecelerate(intparamAmount);
 voidRequestTurn(RelativeDirectionparamDirection);
 voidSetModel(IVehicleModelparamAuto);
 voidSetView(IVehicleViewparamView);
}

  下一个部分对照奇妙。我们但愿View晓得Model中的变更。为了到达这个目标,我们利用察看者形式。

  为了实行察看者形式,我们必要将上面的函数到场到Model(被View察看):AddObserver,RemoveObserver,和NotifyObservers。

publicinterfaceIVehicleModel
{
 stringName{get;set;}
 intSpeed{get;set;}
 intMaxSpeed{get;}
 intMaxTurnSpeed{get;}
 intMaxReverseSpeed{get;}
 AbsoluteDirectionDirection{get;set;}
 voidTurn(RelativeDirectionparamDirection);
 voidAccelerate(intparamAmount);
 voidDecelerate(intparamAmount);
 voidAddObserver(IVehicleViewparamView);
 voidRemoveObserver(IVehicleViewparamView);
 voidNotifyObservers();
}

  ...而且将上面的函数到场到View(被Model察看)中。如许做的目标是Model会有一个View的援用。当Model产生变更时,将会挪用NotifyObservers()办法,传进一个对其本身的援用并挪用Update()关照View这个变更。

publicclassIVehicleView
{
 voidDisableAcceleration();
 voidEnableAcceleration();
 voidDisableDeceleration();
 voidEnableDeceleration();
 voidDisableTurning();
 voidEnableTurning();
 voidUpdate(IVehicleModelparamModel);
}

  如许我们就将我们的接口接洽起来了。鄙人面的代码中我们只必要援用我们这些接口,如许就包管了我们代码的低耦合。任何显现汽车形态的用户界面都必要完成IVehicleView,我们一切的ACME都必要完成IVehicleModel,而且我们必要为我们的ACME汽车制造Controls,这些Control将完成IVehicleControl接口。

  下一步...在common中都必要甚么

  我们晓得一切的汽车都做不异的举措,以是我们接上去做一个基于“骨架”的共有的代码来处置这些操纵。这是一个笼统类,由于我们不但愿任何人在“骨架”上开车(笼统类是不克不及被实例化的)。我们称其为Automobile。我们将用一个ArrayList(fromSystem.Collections)来坚持跟踪一切感乐趣的Views(记着察看者形式了吗?)。我们也能够用老式的数组来纪录对IVehicleView的援用,可是如今我们已很累了想快点停止这篇文章。假如你感乐趣,看一下在察看者形式中AddObserver,RemoveObserver,和NotifyObservers,这些函数是如何和IVehicleView相互感化的。任什么时候间当有速率或偏向变更时,Automobile关照一切的IVehicleViews。

publicabstractclassAutomobile:IVehicleModel
{
 "Declarations"#region"Declarations"
 privateArrayListaList=newArrayList();
 privateintmintSpeed=0;
 privateintmintMaxSpeed=0;
 privateintmintMaxTurnSpeed=0;
 privateintmintMaxReverseSpeed=0;
 privateAbsoluteDirectionmDirection=AbsoluteDirection.North;
 privatestringmstrName="";
 #endregion
 "Constructor"#region"Constructor"
 publicAutomobile(intparamMaxSpeed,intparamMaxTurnSpeed,intparamMaxReverseSpeed,stringparamName)
 {
  this.mintMaxSpeed=paramMaxSpeed;
  this.mintMaxTurnSpeed=paramMaxTurnSpeed;
  this.mintMaxReverseSpeed=paramMaxReverseSpeed;
  this.mstrName=paramName;
 }
 #endregion
 "IVehicleModelMembers"#region"IVehicleModelMembers"
 publicvoidAddObserver(IVehicleViewparamView)
 {
  aList.Add(paramView);
 }
 publicvoidRemoveObserver(IVehicleViewparamView)
 {
  aList.Remove(paramView);
 }
 publicvoidNotifyObservers()
 {
  foreach(IVehicleViewviewinaList)
  {
   view.Update(this);
  }
 }
 publicstringName
 {
  get
  {
   returnthis.mstrName;
  }
  set
  {
   this.mstrName=value;
  }
 }
 publicintSpeed
 {
  get
  {
   returnthis.mintSpeed;
  }
 }
 publicintMaxSpeed
 {
  get
  {
   returnthis.mintMaxSpeed;
  }
 }
 publicintMaxTurnSpeed
 {
  get
  {
   returnthis.mintMaxTurnSpeed;
  }
 }
 publicintMaxReverseSpeed
 {
  get
  {
   returnthis.mintMaxReverseSpeed;
  }
 }
 publicAbsoluteDirectionDirection
 {
  get
  {
   returnthis.mDirection;
  }
 }
 publicvoidTurn(RelativeDirectionparamDirection)
 {
  AbsoluteDirectionnewDirection;
  switch(paramDirection)
  {
   caseRelativeDirection.Right:
    newDirection=(AbsoluteDirection)((int)(this.mDirection+1)%4);
    break;
   caseRelativeDirection.Left:
    newDirection=(AbsoluteDirection)((int)(this.mDirection+3)%4);
    break;
   caseRelativeDirection.Back:
    newDirection=(AbsoluteDirection)((int)(this.mDirection+2)%4);
    break;
   default:
    newDirection=AbsoluteDirection.North;
    break;
  }
  this.mDirection=newDirection;
  this.NotifyObservers();
 }
 publicvoidAccelerate(intparamAmount)
 {
  this.mintSpeed+=paramAmount;
  if(mintSpeed>=this.mintMaxSpeed)mintSpeed=mintMaxSpeed;
  this.NotifyObservers();
 }
 publicvoidDecelerate(intparamAmount)
 {
  this.mintSpeed-=paramAmount;
  if(mintSpeed<=this.mintMaxReverseSpeed)mintSpeed=mintMaxReverseSpeed;
  this.NotifyObservers();
 }
 #endregion
}

  如今我们的"ACMEFramework"已做好了,我们只必要设立无形的类和接口。起首让我们看看最初两个类:Control和Model...

  这里我们无形的AutomobileControl完成IVehicleControl接口。我们的AutomobileControl也将设置View来依附Model的形态(当有向Model的请求时检测SetView办法)。

  注重,我们只是有对IVehicleModel的援用(而不是笼统类Automobile)和对IVehicleView的援用(而不是详细的View),如许包管工具间的低耦合。

publicclassAutomobileControl:IVehicleControl
{
 privateIVehicleModelModel;
 privateIVehicleViewView;
 publicAutomobileControl(IVehicleModelparamModel,IVehicleViewparamView)
 {
  this.Model=paramModel;
  this.View=paramView;
 }
 publicAutomobileControl()
 {}
 IVehicleControlMembers#regionIVehicleControlMembers
 publicvoidSetModel(IVehicleModelparamModel)
 {
  this.Model=paramModel;
 }
 publicvoidSetView(IVehicleViewparamView)
 {
  this.View=paramView;
 }
 publicvoidRequestAccelerate(intparamAmount)
 {
  if(Model!=null)
  {
   Model.Accelerate(paramAmount);
   if(View!=null)SetView();
  }
 }
 publicvoidRequestDecelerate(intparamAmount)
 {
  if(Model!=null)
  {
   Model.Decelerate(paramAmount);
   if(View!=null)SetView();
  }
 }
 publicvoidRequestTurn(RelativeDirectionparamDirection)
 {
  if(Model!=null)
  {
   Model.Turn(paramDirection);
   if(View!=null)SetView();
  }
 }
 #endregion
 publicvoidSetView()
 {
  if(Model.Speed>=Model.MaxSpeed)
  {
   View.DisableAcceleration();
   View.EnableDeceleration();
  }
  elseif(Model.Speed<=Model.MaxReverseSpeed)
  {
   View.DisableDeceleration();
   View.EnableAcceleration();
  }
  else
  {
   View.EnableAcceleration();
   View.EnableDeceleration();
  }
  if(Model.Speed>=Model.MaxTurnSpeed)
  {
   View.DisableTurning();
  }
  else
  {
   View.EnableTurning();
  }
 }
}

  这里是我们的ACME200SportsCar类(从笼统类Automobile承继,完成了IVehicleModel接口):

publicclassACME2000SportsCar:Automobile
{
 publicACME2000SportsCar(stringparamName):base(250,40,-20,paramName){}
 publicACME2000SportsCar(stringparamName,intparamMaxSpeed,intparamMaxTurnSpeed,intparamMaxReverseSpeed):
 base(paramMaxSpeed,paramMaxTurnSpeed,paramMaxReverseSpeed,paramName){}
}

  如今轮到我们的View了...

  如今终究入手下手创建我们MVC最初一个部分了...View!

  我们要创建一个AutoView来完成IVehicleView接口。这个AutoView将会有对Control和Model接口的援用。

publicclassAutoView:System.Windows.Forms.UserControl,IVehicleView
{
 privateIVehicleControlControl=newACME.AutomobileControl();
 privateIVehicleModelModel=newACME.ACME2000SportsCar("Speedy");
}

  我们也必要将一切的器材包装在UserControl的机关函数中。

publicAutoView()
{
 //ThiscallisrequiredbytheWindows.FormsFormDesigner.
 InitializeComponent();
 WireUp(Control,Model);
}
publicvoidWireUp(IVehicleControlparamControl,IVehicleModelparamModel)
{
 //IfwereswitchingModels,dontkeepwatching
 //theoldone!
 if(Model!=null)
 {
  Model.RemoveObserver(this);
 }
 Model=paramModel;
 Control=paramControl;
 Control.SetModel(Model);
 Control.SetView(this);
 Model.AddObserver(this);
}

  上面,到场我们的Button和一个label来显现ACME2000SportsCar的形态另有形态条用来为一切的Buttons来显现编码。

privatevoidbtnAccelerate_Click(objectsender,System.EventArgse)
{
 Control.RequestAccelerate(int.Parse(this.txtAmount.Text));
}
privatevoidbtnDecelerate_Click(objectsender,System.EventArgse)
{
 Control.RequestDecelerate(int.Parse(this.txtAmount.Text));
}
privatevoidbtnLeft_Click(objectsender,System.EventArgse)
{
 Control.RequestTurn(RelativeDirection.Left);
}
privatevoidbtnRight_Click(objectsender,System.EventArgse)
{
 Control.RequestTurn(RelativeDirection.Right);
}

  到场一个办法来更新接口...

publicvoidUpdateInterface(IVehicleModelauto)
{
 this.label1.Text=auto.Name+"heading"+auto.Direction.ToString()+"atspeed:"+auto.Speed.ToString();
 this.pBar.Value=(auto.Speed>0)?auto.Speed*100/auto.MaxSpeed:auto.Speed*100/auto.MaxReverseSpeed;
}

  最初我们完成IVehicleView接口的办法。

publicvoidDisableAcceleration()
{
 this.btnAccelerate.Enabled=false;
}
publicvoidEnableAcceleration()
{
 this.btnAccelerate.Enabled=true;
}
publicvoidDisableDeceleration()
{
 this.btnDecelerate.Enabled=false;
}
publicvoidEnableDeceleration()
{
 this.btnDecelerate.Enabled=true;
}
publicvoidDisableTurning()
{
 this.btnRight.Enabled=this.btnLeft.Enabled=false;
}
publicvoidEnableTurning()
{
 this.btnRight.Enabled=this.btnLeft.Enabled=true;
}
publicvoidUpdate(IVehicleModelparamModel)
{
 this.UpdateInterface(paramModel);
}

  我们终究停止了!!!

  如今我们能够来测试ACME2000SportsCar了。统统按企图举行,然后我们找到ACME的主管职员,但他想要开一个载货卡车而不是活动车。

  侥幸的是我们用的是MVC!我们必要做的一切事情就是创建一个新的ACMETruck类,包装一下,完事!

publicclassACME2000Truck:Automobile
{
 publicACME2000Truck(stringparamName):base(80,25,-12,paramName){}
 publicACME2000Truck(stringparamName,intparamMaxSpeed,intparamMaxTurnSpeed,intparamMaxReverseSpeed):
base(paramMaxSpeed,paramMaxTurnSpeed,paramMaxReverseSpeed,paramName){}
}

  在AutoView中,我们只必要创建卡车包装一下!

privatevoidbtnBuildNew_Click(objectsender,System.EventArgse)
{
 this.autoView1.WireUp(newACME.AutomobileControl(),newACME.ACME2000Truck(this.txtName.Text));
}

  假如我们想要一个新Control只同意我们来每次减速或加速最年夜5mph,小意义!做一个SlowPokeControl(和我们的AutoControl不异,可是在请求减速度中做了限定)。

publicvoidRequestAccelerate(intparamAmount)
{
 if(Model!=null)
 {
  intamount=paramAmount;
  if(amount>5)amount=5;
  Model.Accelerate(amount);
  if(View!=null)SetView();
 }
}
publicvoidRequestDecelerate(intparamAmount)
{
 if(Model!=null)
 {
  intamount=paramAmount;
  if(amount>5)amount=5;
  Model.Accelerate(amount);
  Model.Decelerate(amount);
  if(View!=null)SetView();
 }
}

  假如我们想让我们的ACME2000Truck变得愚钝,只必要在AutoView中包装。

privatevoidbtnBuildNew_Click(objectsender,System.EventArgse)
{
 this.autoView1.WireUp(newACME.SlowPokeControl(),newACME.ACME2000Truck(this.txtName.Text));
}

  最初,假如我们必要一个在web上的接口,我们要做的一切事情就是创建一个Web项目在UserControl中完成IVehicleView接口。

  结论

  正如你所看到的,利用MVC来构建代码把持接口耦合性很低,很简单顺应需求的改动。它也能使变更的影响减小,并且你能够在任何中央重用你的虚函数和接口。有良多时分我们能够在我们的项目中完成伸缩性,出格是在那些需求变更的时分,可是这必要下次再说了。

  于此同时,做下一个项目标时分记着MVC...你不会感应遗憾!也不知道,我同学昨天说数据挖掘很好。

因胸联盟 发表于 2015-1-19 11:34:11

通过这次激烈的讨论,我从大家身上学到了太多,开阔了眼界,不管是支持我的还是骂我的,都感谢你们。

变相怪杰 发表于 2015-1-24 12:38:48

ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。

小女巫 发表于 2015-2-1 11:52:43

比如封装性、继承性、多态性等等,这就解决了刚才谈到的ASP的那些弱点。封装性使得代码逻辑清晰,易于管理,并且应用到ASP.Net上就可以使业务逻辑和Html页面分离,这样无论页面原型如何改变。

海妖 发表于 2015-2-7 04:41:43

ASP.Net摆脱了以前ASP使用脚本语言来编程的缺点,理论上可以使用任何编程语言包括C++,VB,JS等等,当然,最合适的编程语言还是MS为.NetFrmaework专门推出的C(读csharp)。

再现理想 发表于 2015-2-20 14:16:23

ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。

简单生活 发表于 2015-3-6 18:09:31

网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项!

柔情似水 发表于 2015-3-13 05:08:28

关于ASP.NET功能上,ASP.NET比微软以前的ASP(96年出现)有更强大的library,更好的稳定性。ASP.NET可以使用.NETFramework中所有组件(也就是说.NET能实现的,ASP.NET一样能实现)。

老尸 发表于 2015-3-20 13:32:44

主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。
页: [1]
查看完整版本: ASP.NET教程之用Visual C#完成MVC形式的扼要办法