架構 : 三層架構、MVC、MVP、MVVM

一、 三層架構

 
將整個業務應用劃分爲:界面層(User Interface layer, UIL)、業務邏輯層(Business Logic Layer, BLL)、數據訪問層(Data access layer, DAL)。
 
 
1:界面層: 主要是指用戶交互的界面。用於接收用戶輸入的數據和顯示處理後用戶須要的數據。若是邏輯層至關強大和完善,不管表現層如何定義和更改,邏輯層都能完善地提供服務。
 
2:業務邏輯層: UI層和DAL層之間的橋樑實現業務邏輯。業務邏輯具體包含:驗證、計算、業務規則等等。
 
3:數據訪問層:與數據庫打交道。主要實現對數據的增、刪、改、查。將存儲在數據庫中的數據提交給業務層,同時將業務層處理的數據保存到數據庫。(固然這些操做都是基於UI層的。用戶的需求反映給界面(UI),UI反映給BLLBLL反映給DALDAL進行數據的操做,操做後再一一返回,直到將用戶所需數據反饋給用戶)。
 
   

1.一、 規則

  1. 最關鍵的,UI層只能做爲一個外殼,不能包含任何業務邏輯(BizLogic)的處理過程。只有少許(或者沒有)SQL語句或者存儲過程的調用,而且這些語句保證不會修改數據。
  2. 設計時應該從BLL出發,而不是UI出發。BLL層在API上應該實現全部BizLogic(以面向對象的方式)。若是把UILayer拿掉,項目還能在Interface/API的層次上提供全部功能)。
  3. 無論數據層是一個簡單的SqlHelper也好,仍是帶有Mapping過的Classes也好,應該在必定的抽象程度上作到系統無關(DAL能夠移植到其餘相似環境的項目)。
  4. 無論使用COM+(Enterprise Service),仍是Remoting,仍是WebService之類的遠程對象技術,無論部署的時候是否是真的分別部署到不一樣的服務器上,最起碼在設計的時候要作這樣的考慮,更遠的,還得考慮多臺服務器經過負載均衡做集羣(三個模塊,能夠分別運行於不一樣的服務器)。

1.二、 優點

1,結構清晰、耦合度低,html

2,可維護性高,可擴展性高;程序員

3,利於開發任務同步進行;容易適應需求變化數據庫

1.三、 劣勢

一、有時會致使級聯的修改。這種修改尤爲體如今自上而下的方向。若是在表示層中須要增長一個功能,爲保證其設計符合分層式結構,可能須要在相應的業務邏輯層和數據訪問層中都增長相應的代碼編程

二、增長了代碼量,增長了工做量,增長了複雜度。服務器

 

二、 MVC

 

 

若是說ORM(Object Relation Mapping)等框架是數據訪問層的框架模式,解除了業務邏輯和數據之間的耦合,業務邏輯再也不關心底層數據如何存儲和讀取。全部數據呈現給業務邏輯層的就是一個個的對象。

MVC則是表現層的框架模式。用於解除業務邏輯和視圖之間的耦合。從而易於擴展,便於測試。架構

 

MVC誕生於1979年,體現了「關注點分離」這一設計方針,它將一我的機交互應用涉及的功能分爲三部分。

2.一、 Model

Model對應應用狀態和業務功能的封裝,能夠將它理解爲同時包含數據和行爲的領域模型(Domain Model)。Model接受Controller的請求並完成相應的業務處理,在應用狀態改變的時候能夠向View發出相應的通知。

2.二、 View

View實現可視化界面的呈現並捕捉最終用戶的交互操做。View能夠直接調用Model查詢其狀態信息,而Model也能夠在本身的狀態發生改變時,主動通知View。

2.三、 Controller

Contoller是M和V之間的鏈接器,用於控制應用程序的流程。View捕獲用戶交互操做後直接轉發給Contoller,後者完成相應的UI邏輯。若是須要涉及業務功能的調用,Contoller會直接調用Model及修改Model狀態。Contoller也能夠主動控制原View或建立新的View對用戶交互操做予以響應。
 

2.一、 MVC使用的誤區

2.1.一、 把Model理解成實體類(Entity)

在MVC中Model應該包含2部分功能,一部分是處理業務邏輯,一部分是提供View顯示的數據。app

它應該是業務邏輯真正的實現層。因此Model的其實是Business Model(業務模型)。而Controller僅僅起一個「橋樑」做用,它負責把View的請求轉發給Model,再負責把Model處理結束的消息通知View。Controller的存在是爲了使UI界面、UI邏輯、業務邏輯之間分離。

2.1.二、 大量業務邏輯代碼堆積在Controller端

MVC中的控制器,內裏封裝了通信,容易變成大而全 的高度耦合的集中器。
  1. 控制器中寫業務代碼
    1. UI邏輯能夠寫在Controller中,而業務邏輯應該在Model裏,Controller只是去調用它們。
  2. 控制器變得依賴信息數據中心或數據庫,對象將間接地經過控制器的action耦合在一塊兒負載均衡

    1. 能夠經過引入IOC容器來解決

2.二、 總結

MVC最先的定義畢竟是79年提出的,到如今GUI編程環境,業務複雜程度都有了很大改變。當採用MVC模式設計UI應用時,通常會根據開發框架的特色來對Model,View和Contoller設置一個明確的界限,同時爲它們之間的交互制定一個更加嚴格的規則。

三、 MVC變體

在軟件發展歷程中出現了一些MVC變體,它們遵循定義在MVC中的基本原則,但對三元素直接的交互制定了更爲嚴格的規範。

3.一、 MVP

  1. MVP適用於基於事件驅動的應用框架中,如Asp.net Web Forms 和Windows Forms應用。
  2. MVP中嚴格禁止View和Model間的直接交互,必需經過Presenter來完成。Model的獨立性獲得了真正的體現,它不只僅與可視化元素的呈現(View)無關,與UI處理邏輯也無關。使用MVP的應用是用戶驅動而不是Model驅動,因此Model不須要主動通知view。
  3. MVP模式中的V表明的是一個接口,一個將UI界面提煉而抽象出來的接口。接口意味着任何實現了該接口的界面,都可以複用已有的Presenter和Model代碼。是真正意義上的隔離View的細節和複雜性的模式,下降了Presenter對View的依賴。帶來的好處就是定義在Presenter中的UI處理邏輯變得易於測試。
 
MVP中Presenter與Model的交互很清晰,僅體現爲Presenter對Model的單向調用。而View與Presenter直接的交互方式就成了MVP的核心。按照View與Presenter的交互方式依據View自己的職責範圍,Martin Folwer將MVP分爲PV(Passive View)和SC(Supervising Contoller)兩種模式。

3.1.一、 PV

view是難以測試的,經過讓它儘量不涉及UI處理邏輯來使它不須要測試,這就是PV模式的目的。
這意味着須要將View中的UI元素經過屬性的形式暴露出來。將全部UI處理邏輯所有定義到Presenter中。定義在IView裏的只有屬性。

3.1.二、 SC

PV須要將View中可供操做的UI元素定義在對應的接口中,對於一些複雜的富客戶端應用的View來講,接口成員的數量可能會很是多,這無疑提高了代碼量和Presenter的複雜度。
SC則將一些單純,獨立的UI邏輯交由View自身來完成。固然它處理的數據是Presenter實時推送給它的。View儘量不維護數據狀態。定義在IView裏的接口儘可能只包含方法,且是無返回值的方法(單向傳遞消息)。
 
Models:
public class Employee
{
     public  string  Id {  get private  set ; }
     public  string  Name {  get private  set ; }
     public  string  Gender {  get private  set ; }
     public  DateTime BirthDate {  get private  set ; }
     public  string  Department {  get private  set ; }
 
     public  Employee( string  id, string  name, string  gender,DateTime birthDate, string  department)
     {
         Id          = id;
         Name        = name;
         Gender      = gender;
         BirthDate   = birthDate;
         Department  = department;
     }
}
 
public  class  EmployeeRespository
{
     private  static  IList<Employee> employees;
 
     static  EmployeeRespository()
     {
         employees =  new  List<Employee>()
         {
             new  Employee( "001" , "張三" , "男" , new  DateTime(1981,8,24), "銷售部" ),
             new  Employee( "002" , "李四" , "男" , new  DateTime(1981,8,24), "人事部" ),
             new  Employee( "003" , "王五" , "女" , new  DateTime(1981,8,24), "人事部" )
         };
     }
 
     public  IEnumerable<Employee> GetEmployees( string  department =  "" )
     {
         if  ( string .IsNullOrEmpty(department))
         {
             return  employees;
         }
         return  employees.Where(e => e.Department == department).ToArray();
     }
}

 
Presenter、IView
public class EmployeePresenter
{
     public  IEmployeeView View {  get private  set ; }
     public  EmployeeRespository Respository {  get private  set ; }
 
     public  EmployeePresenter(IEmployeeView view)
     {
         this .View = view;
         this .Respository =  new  EmployeeRespository();
         this .View.DepartmentSelected += OnDepartmentSelected;
     }
 
     public  void  Initialize()
     {
         IEnumerable<Employee> employees =  this .Respository.GetEmployees();
         this .View.BindEmployees(employees);
         string [] departments
             new  string []{
                 "" , "銷售部" , "採購部" , "人事部"
             };
         this .View.BindDepartments(departments);
     }
 
     protected  void  OnDepartmentSelected( object  sender, DepartmentSelectedEventArgs args)
     {
         string  department = args.Department;
         var  employees =  this .Respository.GetEmployees(department);
         this .View.BindEmployees(employees);
     }
}
 
 
public  interface  IEmployeeView
{
     void  BindEmployees(IEnumerable<Employee> employees);
     void  BindDepartments(IEnumerable< string > departments);
     event  EventHandler<DepartmentSelectedEventArgs> DepartmentSelected;
}
public  class  DepartmentSelectedEventArgs : EventArgs
{
     public  string  Department {  get private  set ; }
     public  DepartmentSelectedEventArgs( string  department)
     {
         this .Department = department;
     }
}
WinForm實現的UI界面
public  partial  class  Form1 : Form, IEmployeeView
{
     private  EmployeePresenter Presenter{  get private  set ; }
     public  Form1()
     {
         InitializeComponent();
 
         Presenter =  new  EmployeePresenter( this );
         Presenter.Initialize();      
     }
     public  event  EventHandler<DepartmentSelectedEventArgs> DepartmentSelected;
 
     public  void  BindDepartments(IEnumerable< string > departments)
     {
         this .comboBox1.DataSource = departments;
     }
 
     public  void  BindEmployees(IEnumerable<Employee> employees)
     {
         this .listBox1.DataSource = employees;
         this .listBox1.DisplayMember =  "Name" ;
     }
 
     private  void  comboBox1_SelectedIndexChanged( object  sender, EventArgs e)
     {
         string  department = ( string ) this .comboBox1.SelectedItem;
         DepartmentSelectedEventArgs eventArgs =  new  DepartmentSelectedEventArgs(department);
         DepartmentSelected?.Invoke(sender, eventArgs);
     }
}

 

WebForm實現的UI界面
public  partial  class  Default : Page, IEmployeeView
{
     public  EmployeePresenter Presenter {  get private  set ; }
     public  event  EventHandler<DepartmentSelectedEventArgs> DepartmentSelected;
 
     public  Default()
     {
         this .Presenter =  new  EmployeePresenter( this );
     }
 
     protected  void  Page_Load( object  sender, EventArgs e)
     {
         if  (! this .IsPostBack)
         {
             this .Presenter.Initialize();
         }
     }
 
     protected  void  ButtonSearch_Click( object  sender, EventArgs e)
     {
         string  department =  this .DropDownListDepartments.SelectedValue;
         DepartmentSelectedEventArgs eventArgs =  new  DepartmentSelectedEventArgs(department);
         if  ( null  != DepartmentSelected)
         {
             DepartmentSelected( this , eventArgs);
         }
     }
 
     public  void  BindEmployees(IEnumerable<Employee> employees)
     {
         this .GridViewEmployees.DataSource = employees;
         this .GridViewEmployees.DataBind();
     }
 
 
     public  void  BindDepartments(IEnumerable< string > departments)
     {
         this .DropDownListDepartments.DataSource = departments;
         this .DropDownListDepartments.DataBind();
     }
}

在MVP裏,能夠根據User Story來首先設計和開發Presenter。在這個過程當中,View是很簡單的,可以把信息顯示清楚就能夠了。在後面,根據須要再隨便更改View, 而對Presenter沒有任何的影響了。框架

若是要實現的UI比較複雜,並且相關的顯示邏輯還跟Model有關係,能夠在View和 Presenter之間放置一個Adapter。由這個 Adapter來訪問Model和View,避免二者之間的關聯。而同時,由於Adapter實現了View的接口,從而能夠保證與Presenter之 間接口的不變。這樣就能夠保證View和Presenter之間接口的簡潔,又不失去UI的靈活性。函數

3.二、 MVVM

MVVM模式中,一個ViewModel和一個View匹配,它沒有MVP中的IView接口,而是徹底的和View綁定,全部View中的修改變化,都會自動更新到ViewModel中,同時ViewModel的任何變化也會自動同步到View上顯示。
這種自動同步之因此可以的緣由是ViewModel中的屬性都實現了observable這樣的接口,也就是說當使用屬性的set的方法,都會同時觸發屬性修改的事件,使綁定的UI自動刷新。(在WPF中,這個observable接口是 INotifyPropertyChanged; 在knockoutjs中,是經過函數ko.observable() 和ko.observrableCollection()來實現的)
在MVP中,V是接口IView, 解決對於界面UI的耦合; 而MVVM則乾脆直接使用ViewModel和UI無縫結合, ViewModel直接就能表明UI。可是MVVM作到這點是要依賴具體的平臺和技術實現。 這也就是爲何ViewModel不須要實現接口的緣由,由於對於具體平臺和技術的依賴,本質上使用MVVM模式就是不能替換UI的使用平臺的。
MVVM的提出源於WPF,主要是用於分離應用界面層和業務邏輯層。WPF/Siverlight是基於數據驅動開發的。
在MVC和MVP模式中, 開發View層的是程序員, 雖然UI/UE團隊會作不少工做, 但這個層的"實現者"仍然是程序員。
而在WPF開發中將View層的代碼邏輯抽取出來,並使View層很純粹以便徹底讓美工去打造它。相應地, 須要將View層的相應邏輯抽取到一個代碼層上,以便讓程序員專一在這裏。

3.三、 Asp.net Mvc 應用中的請求處理

  • 每一個HTTP請求的目標是Controller中的一個Action,具體體現爲定義在Controller類型中的一個public方法。因此對請求的處理最終體現爲對目標Controller對象的激活和對目標Action方法的執行。
  • Controller的類型和Action方法的名稱及做爲Action方法的部分參數能夠直接經過請求的Url解析出來。
  • 經過一個攔截器(Interceptor)對抵達Web服務器的HTTP請求進行攔截。這個攔截器根據當前請求解析出目標Controller的類型和對應的Action方法的名稱,隨後目標Controller被激活,相應的Action方法被執行。
  • Action方法執行過程當中,能夠調用Model獲取相應的數據及改變其狀態。在Action執行的最後階段通常會建立一個View,後者最終被轉換爲HTML以HTTP響應的形式返回到客戶端。
  • 綁定在View上的數據稱爲ViewModel,來源於Model或者基於顯示要求進行的簡單邏輯計算。它與MVVM中的ViewModel是徹底不一樣的概念,後者不只包括呈如今View中的數據,也包括數據操做行爲。

 


 轉載自:http://www.cnblogs.com/wj033/p/5812938.html

相關文章
相關標籤/搜索