##一、前言
????? 大家好,接近一年的時間沒有怎么書寫博客了,一方面是工作上比較忙,同時生活上也步入正軌,事情比較繁多,目前總算是趨于穩定,可以有時間來完善以前沒有寫完的系列,也算是對自己這段時間工作和生活上總結,同時也加深下自己對架構和
設計方面的理解,由于本人的寫作水平有限,所以在書寫的深度和書寫的格式上還有很多的缺點,還希望大家多多指出。
##二、開篇
????? 本篇我們將針對系統架構中的分層進行講述,分析不同分層模式的優缺點及應用的場景,當然我們會結合一些案例來介紹這些分層,通過案例來證明各種分層的好處與優缺點,本篇作為開篇主要是介紹這個分層系列中會講述到的幾種分層模式實踐,
由于很多分層模式也是自己在工作過程中總結和經驗積累下來的,可能存在個人理解或用法上錯誤之處,還請大家指出,我予以及時更正。
##三、內容提要
????? 1、前言
????? 2、開篇
????? 3、本文提綱
????? 4、分層模式
??????????? 4.1、分層架構介紹
??????????? 4.1、后端分層多層
????????????????? 4.1.1、普通三層架構
????????????????? 4.1.2、多層架構
??????????? 4.2、前端分層模式
????????????????? 4.2.1、MVC模式
????????????????? 4.2.2、MVP模式
????????????????? 4.2.3、MVVM模式
????? 5、結束語
????? 6、系列進度
????? 7、下篇預告
##四、分層模式
?
4.1、分層架構介紹
??????? 架構首先是分為不同層次的和不同視圖的,例如架構有五種視圖:邏輯視圖、物理視圖、數據視圖、運行視圖、開發視圖。我們今天不講解這幾個不同的視圖,而是講解分層對于軟件設計的意義及關注點,之前我也發過一片單機軟件架構的文章,文
章中提到了一個軟件從簡單到復雜的全過程,而軟件架構也是一個迭代的過程,是一個循序漸進,不斷完善的過程。
??????? 我們今天交流的主要是邏輯緯度的分層,關于物理視圖的分層,本篇先不講解,因為那塊更復雜,同時也更重要,對于大型的互聯網軟件或大型的互聯網網站,更關注的是物理架構方面的設計。下面我們就來針對當前的一些分層模式來進行講解,并
且進行簡要的分析和應用場景介紹。
4.2、后端分層架構
一、普通三層架構
三層架構(3-tier architecture) 通常意義上的三層架構就是將整個業務應用劃分為:表現層(UI)、業務邏輯層(BLL)、數據訪問層(DAL)。區分層次的目的即為了“高內聚,低耦合”的思想。
[](http://images.cnitblog.com/blog/46256/201312/24222637-f3f016ce26bf4da3ba3958992907d742.png)
三層架構圖
??????? 對于傳統的三層架構圖,可能因為大家在實際的場景中,因為大家對這些分層運用的不同,會出現適應的場景的不同,而且有很多的大型軟件或項目,都是采用三層架構,我們可以通過引入一些開源的組件或自定義組件來構建非常靈活或擴展性很強
的分層結構,雖然是3層架構,但是卻可以滿足大部分的場景。
A、場景:
最原始的三層結構可能如下:
[](http://images.cnitblog.com/blog/46256/201312/24222639-3b3e215e16b84a87ac63e53cf4c234fd.png)
ThreeArchitecture.Entities:實體定義層,該層主要是完成各分層間數據傳遞并且最終通過該實體實現DAL層與數據庫交互的數據傳輸。
ThreeArchitecture.DAL:數據訪問層,通過調用實體層,通過Ado.net編程,實現數據持久化,例如可以支持多種數據庫,sqlserver、oracle、mysql、sqlite.
ThreeArchitecture.BLL:業務邏輯層,通過調用實體層、數據訪問層,實現整個業務系統的核心功能,完成系統業務的處理。
ThreeArchitecture.UI:用戶界面交互層,用戶通過該用戶界面與業務系統進行交互,完成業務邏輯操作與交互。
根據上面的解決方案的分層及組織,下面針對以下幾個場景來分析,分析三層架構中遇到的問題,應該如何解決這些問題。
1)、如果需要實現多數據庫支持。我想業務系統能夠從sqlserver向oracle數據遷移,或反之。
這樣在現有的項目結構方式,就無法滿足,但是我們可以增加新的接口層來實現這個要求。
例如可以通過如下項目方式來組織:
[](http://images.cnitblog.com/blog/46256/201312/24222640-7e9e7b598e58464b81f34bbf81102ce9.png)
修改原有的項目劃分結構,加入DAL.Interface層次。定義數據訪問接口,通過不同的數據訪問實現,然后通過數據訪問層工廠,來構建不同的數據庫訪問實例。
這塊具體的代碼我就不貼出了,應該比較簡單。
同時原來的ThreeArchitecture.BLL 調用的不是直接調用數據庫訪問層實現,而是調用數據訪問層接口。不依賴于具體的實現,而是依賴接口,這樣可以實現解耦,提供了很強的擴展性。
2)、如果我要求業務邏輯層實現也不一定固定,例如在醫療行業的話,每個醫院的業務系統或業務流程都不相同,那么假設我們希望溝通統一的UI界面,而不是隨著業務邏輯的改變而修改UI,那么我們就需要進行如下的設計:
項目的結構方式類似上面的DAL層的變化。
[](http://images.cnitblog.com/blog/46256/201312/24222641-fe6f2a2e3d95468e97823d2853780887.png)
在原來的基礎上改進:
ThreeArchitecture.BLL.Interface:定義業務邏輯接口,主要目標是隔離UI與業務邏輯實現間的依賴關系,將實現代碼調用修改為接口調用方式。
ThreeArchitecture.BLL.A:A場景下的實現,A的業務邏輯。
ThreeArchitecture.BLL.B:B場景下的實現,B的業務邏輯。
3)、縱向和橫向擴展性需求場景,例如場景變化靈活性較高時,工廠模式無法很好應對,需要維護大量的工廠代碼。
可以采用開源的相關組件,來實現解耦及隔離,例如 數據訪問層可以采用Nhibernate或Entityframework來實現,關于Nhibernate的文章,園子里面已經有很多的文章介紹了,我就不介紹了,
引入Nhibernate以后,項目的結構,回到如下模式
[](http://images.cnitblog.com/blog/46256/201312/24222643-fc2172a550934b2b9d3272859fbb0c1d.png)
ThreeArchitecture.DAL.Nhibernate:NHibernate實現數據訪問層接口,Nhibernate支持目錄主流的大部分數據庫,所以不需要按照1)中的方案去做,只需要實現一次即可。
ThreeArchitecture.DAL.EntityFramework:EntityFramework實現數據訪問層接口,EntityFramework支持Oracle,SQLServer,其他的數據庫支持的不太好。
在上面的場景中,例如在A場景下,我希望使用A業務層、B場景下使用B實現,而且,不希望系統中維護大量的工廠代碼,那么我們就請出來當前架構或框架設計的核心組件IOC
IOC:控制反轉(Inversion of Control,英文縮寫為IoC)是一個重要的[面向對象編程](http://baike.baidu.com/view/10110.htm)的法則來削減計算機程序的耦合問題,也是當前主流框架的核心。 控制反轉還有一個名字叫做依賴注入(Dependency Injection)。簡稱DI。
采用了IOC以后,接口和實現就可以通過配置的方式來動態的設置,而且調用的方式也變得更簡單,不需要其他復雜的代碼設定,目前市面上的IOC容器很多,我了解的主要是以下幾種:
Unity:微軟的輕量級IOC容器。提供了比較強的注冊和動態查找機制,同時提供了強大的AOP,幾乎無所不在。
Autofac:Autofac是一款IOC框架,比較于其他的IOC框架,如Spring.NET,Unity,Castle等等所包含的,它很輕量級性能上也是很高的
Spring.NET:參考java的sprint 框架的.net平臺下的實現,比較強大。
Castle:Castle是針對.NET平臺下的一個非常優秀的開源項目,從數據訪問框架 ORM到依賴注入容器,再到WEB層的MVC框架、AOP,基本包括了整個開發過程中的所有東西,為我們快速的構建企業級的[應用程序](http://baike.baidu.com/view/330120.htm)提供了很好的服務
Ninject:是一個快如閃電、超輕量級的基于.Net平臺的依賴注入框架。它能夠幫助你把應用程序分離成一個個松耦合、高內聚的模塊,然后用一種靈活的方式組裝起來。通過使用Ninject配套你的軟件架構,那么代碼將會變得更加容易編寫、重用性強、
易于測試和修改。
關于上面介紹的部分IOC容器的用法整體上來說都差不多,具體的大家可以網上搜索下,案例和demo比較多。
二、多層架構
上面介紹了普通的三層架構,多層架構顧名思義就是在三層架構之上,通過擴展及應用場景的挖掘,衍生出來的適應不同場景的架構模式,下面我主要是來介紹以下幾種多層架構模式
A、服務層模式
在上面介紹的3層架構模式中,存在一個缺陷,如果我們構建的軟件或系統支持分布式或者需要對外提供服務的時候,這個場景就無法滿足了,所以這個時候服務層就出現了,就是在BLL層的基礎上進行包裝,包裝成可以對外提供調用的分布式服務。
經過改造后的項目結構如下:
[](http://images.cnitblog.com/blog/46256/201312/24222644-55626cd4313f4876af26157b1f01dab4.png)
在項目中加入了03.解決方案文件夾,同時添加項目 ThreeArchitecture.Service項目。
ThreeArchitecture.Service:主要是提供幾個作用:1、將業務邏輯層進行封裝,對外提供業務服務調用。2、通過外觀模式,屏蔽業務邏輯內部方法。3、降低業務邏輯層與UI層的依賴,業務邏輯接口或實現的變化不會影像UI層。4、降低UI層調用的請求次
數及數據往返。
在上面的結構中,我們說了Service層次的作用,目前還少加入了一層,DTO(數據傳輸對象層),該層負責屏蔽后端的實體層,將UI層需要的數據進行重新的定義和封裝,在實際的業務場景下,后端實現或存儲的數據遠比用戶需要的數據要龐大和負責,所
以前端需要的數據相對來說要么是組合的,要么是抽取的,不是完整的,因為我們在設計數據存儲格式上都會有一些額外的設計和考慮。
[](http://images.cnitblog.com/blog/46256/201312/24222646-7bff1f540ccb4bbb876cdf7e906778c6.png)
加入了ThreeArchitecture.DTO層后,前端的UI層,只是知道DTO的存在,同時前端需要的數據都在一個Dto中,這樣,每次調用服務層的時候,只需要調用一次就可以完成所有的業務邏輯操作,而不是原來的直接調用業務邏輯層那樣的,需要調用多
次,對于分布式場景下,減少服務調用的次數,尤其重要。
B、DDD架構模式:
[](http://files.dotblogs.com.tw/jed/1007/DomainDrivenDesign_964D/image_6.png)
Presentation Layer: 負責與客戶端進行交互
Application Layer: 負責協調領域層之間的交互
Domain Layer: 軟件的核心,所有相關的Domain information都在這,可以看成是Business Logic Layer,但不完全是
Infrastructure Layer: 負責各層之間的交互溝通、資料存取、安全性管理及通用Library
更常見的是如下層次

我們建議的方式如下:

Repository層使用ORM映射或SQL命令等方式把持久化數據轉化為領域對象,然后根據業務邏輯設計對應領域層服務Domain Service 。接著應用層進行操作上的協調,利用Repository、領域模型、領域層服務Domain Service 完成業務需要,再通過數
據轉換器把領域對象Domain Object轉化為數據傳輸對象DTO。最后,利用遠程通訊技術把應用層的服務(Application Service)對外開放。
注意留意的是SOA系統中,UI表現層與Application Service應用層服務是實現分離的,表現層可以同時調用多方的遠程服務來完成工作。
在上面的架構中還可以加入領域事件、查詢接口、分布式服務層,來靈活運用和組合,來解決項目中適應場景的不同。
4.3、前端分層架構
A、MVC架構模式
MVC全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,一種軟件設計典范,用一種業務邏輯和數據顯示分離的方法組織代碼,將業務邏輯被聚集到一個部件里面,在界面和用戶圍繞數據的交互能被改進和個性化
定制的同時而不需要重新編寫業務邏輯。MVC被獨特的發展起來用于映射傳統的輸入、處理和輸出功能在一個邏輯的圖形化用戶界面的結構中。

目前在主流的框架中都支持該模式,例如構建winform程序中可以通過MVC模式來分離界面層中的控件與后端服務間的交互。降低耦合及依賴。
web上通過asp.net MVC框架來實現前端頁面及后端控制器之間的隔離。
##### ?????? 視圖
視圖是用戶看到并與之交互的界面。對老式的Web應用程序來說,視圖就是由HTML元素組成的界面,在新式的Web應用程序中,HTML依舊在視圖中扮演著重要的角色,但一些新的技術已層出不窮,它們包括Adobe Flash和像XHTML,XML/XSL,WML
等一些標識語言和Web services.
MVC好處是它能為應用程序處理很多不同的[視圖](http://baike.baidu.com/view/71981.htm)。在視圖中其實沒有真正的處理發生,不管這些數據是聯機存儲的還是一個雇員列表,作為視圖來講,它只是作為一種輸出數據并允許用戶操縱的方式。
##### ?????? 模型
模型表示企業數據和業務規則。在MVC的三個部件中,模型擁有最多的處理任務。一個模型能為多個視圖提供數據,由于應用于模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復性。
##### ?????? 控制器
控制器接受用戶的輸入并調用模型和視圖去完成用戶的需求,所以當單擊[Web](http://baike.baidu.com/view/3912.htm)頁面中的超鏈接和發送[HTML表單](http://baike.baidu.com/view/3488030.htm)時,控制器本身不輸出任何東西和做任何處理。它只是接收請求并決定調用哪個模型構件去處理請求,然后再確定用哪個視圖來顯示返回的數
據。
ASP.NET MVC
[](http://images.cnitblog.com/blog/46256/201312/24222649-ac425b4781d04b08a468476d540fc53d.png)
關于具體的代碼,大家可以嘗試新建一個MVC的應用程序,微軟提供的默認的MVC的代碼模版中就有相關的示例代碼,具體的我就不介紹了。
Winform的MVC模式
[](http://images.cnitblog.com/blog/46256/201312/24222654-49a1721f6a6a44bda5d3979b2c8cb0aa.png)
winform的MVC模式,主要是通過事件的方式來實現。
?
B、MVP架構模式
?????? MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。作為一種新的模式,MVP與MVC有著一個重大的區別:在MVP中View并不直接使用Model,它們之間
的通信是通過Presenter (MVC中的Controller)來進行的,所有的交互都發生在Presenter內部,而在MVC中View會從直接Model中讀取數據而不是通過 Controller。
????? 在MVC里,View是可以直接訪問Model的!從而,View里會包含Model信息,不可避免的還要包括一些業務邏輯。 在MVC模型里,更關注的Model的不變,而同時有多個對Model的不同顯示,及View。所以,在MVC模型里,Model不依賴于Vie
w,但是View是依賴于Model的。不僅如此,因為有一些業務邏輯在View里實現了,導致要更改View也是比較困難的,至少那些業務邏輯是無法重用的。

1、View和Model完全解耦,兩者不發生直接關聯,通過Presenter進行通信。
2、Presenter并不是與具體的View耦合,而是和一個抽象的View Interface耦合,View Interface相當于一個契約,抽象出了對應View應實現的方法。只要實現了這個接口,任何View都可以與指定Presenter兼容,從而實現了P Logic的復用性和視圖的無縫替換。
3、View在MVP里應該是一個“極瘦”的概念,最多也只能包含維護自身狀態的邏輯,而其它邏輯都應實現在Presenter中。
總的來說,使用MVP模式可以得到以下兩個收益:
1、將UI和P Logic兩個關注點分離,得到更干凈和單一的代碼結構。
2、實現了P Logic的復用以及View的無縫替換。
[](http://images.cnitblog.com/blog/46256/201312/24222657-64d1c39ae7a54b728db71edf8126c248.png)
展示器層作為核心的控制,實現view和model之間的完全解耦。關于該架構設計的具體demo 后面來介紹
C、MVVM架構模式
????? MVVM是Model-View-ViewModel的簡寫。
??????[微軟](http://baike.baidu.com/view/2353.htm)的WPF帶來了新的技術體驗,如Sliverlight、音頻、視頻、3D、動畫……,這導致了[軟件](http://baike.baidu.com/view/37.htm)UI層更加細節化、可定制化。同時,在技術層面,WPF也帶來了 諸如Binding、Dependency Property、Routed Events、Command、DataTemplate、C
ontrolTemplate等新特性。MVVM(Model-View-ViewModel)框架的由來便是MVP(Model-View-Presenter)模式與WPF結合的應用方式時發展演變過來的一種新型架構框架。它立足于原有MVP框架并且把WPF的新特性揉合進去,以應對客戶日
益復雜的需求變化。
MVVM模式和MVC模式一樣,主要目的是分離視圖(View)和模型(Model),有幾大優點
1. 低耦合。視圖(View)可以獨立于Model變化和修改,一個ViewModel可以綁定到不同的"View"上,當View變化的時候Model可以不變,當Model變化的時候View也可以不變。
2. 可重用性。你可以把一些視圖邏輯放在一個ViewModel里面,讓很多view重用這段視圖邏輯。
3. 獨立開發。開發人員可以專注于業務邏輯和數據的開發(ViewModel),設計人員可以專注于頁面設計,使用Expression Blend可以很容易設計界面并生成xaml代碼。
4. 可測試。界面素來是比較難于測試的,而現在測試可以針對ViewModel來寫。

1.?視圖(View)
視圖負責界面和顯示。它通過DataContext(數據上下文)和ViewModel進行數據綁定,不直接與Model交互。 可以綁定Behavior/Comand來調用ViewModel的方法,Command是View到ViewModel的單向通行,通過實現Silverlight提供的IComand接口來實現綁定,讓View觸發事件,ViewModel來處理事件,以解決事件綁定功能。
2.?視圖模型(ViewModel)
視圖模型主要包括界面邏輯和模型數據封裝,Behavior/Command事件響應處理,綁定屬性定義和集合等。它是View和Model的橋梁,是對Model的抽象,比如:Model中數據格式是“年月日”,可以在ViewModel中轉換Model的數據為“日月年”供View顯示。
實現視圖模型需要實現Silverlight提供的接口INotifyPropertyChanged, INotifyPropertyChanged接口用于實現屬性和集合的變更通知(Change Notifications)。使得在用戶在視圖上所做的操作都可以實時通知到視圖模型,從而讓視圖模型對象有的模型進行正確的業務操作。
View的代碼隱藏(Code-Behind)部分可能包含界面邏輯或者應用邏輯的代碼,這些代碼會很難進行單元測試,應根據具體情況盡量避免。
3.?模型(Model)
Model與MVC模式一樣,Model用于封裝與應用程序的業務邏輯相關的數據以及對數據的處理方法。它具有對數據直接訪問的權利,例如對數據庫的訪問,Model不依賴于View和ViewModel,也就是說,模型不關心會被如何顯示或是如何被操作,
模型也不能包含任何用戶使用的與界面相關的邏輯。Model在實際開發中根據實際情況可以進行細分。比如在廣州市城鄉規劃資源平臺就將Model將Service和Reposiroty結合為WCF服務由ViewModel進行調用。
一般來說實際的項目中會采用以下的模式來做,而不是直接采用傳統的MVVM模式,而是結合MVP或MVC模式來做。
[](http://images.cnitblog.com/blog/46256/201312/24222700-c7b65ab1a5564b0a9033c755d9c46b89.png)
????????? 上圖中的P層是整個項目的核心,負責處理View層顯示的數據來源及用戶操作的響應的處理,通過綁定viewModel中的command的處理來與后端服務進行交互,展示器層會調用后端的WCF服務來讀取數據,也就是讀取DataModel 然后修改View
Model。通過WPF提供的通知機制,來修改view的呈現。
MVC、MVP、MVVM對比
<table cellspacing="0" cellpadding="2" width="1013" border="0" style="margin:0px; padding:0px; border-collapse:collapse; border-spacing:0px; border:1px solid rgb(192,192,192); color:rgb(0,0,0); font-family:Verdana,Arial,Helvetica,sans-serif; font-size:14px; line-height:21px"><tbody style="margin:0px; padding:0px"><tr style="margin:0px; padding:0px"><td valign="top" width="95" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">標題?<br style="margin:0px; padding:0px"/></td><td valign="top" width="270" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">MVC</td><td valign="top" width="281" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">MVP</td><td valign="top" width="365" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">MVVM</td></tr><tr style="margin:0px; padding:0px"><td valign="top" width="95" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">特點?<br style="margin:0px; padding:0px"/></td><td valign="top" width="270" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">高內聚、低耦合-一個控制器可以控制多個視圖</td><td valign="top" width="281" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">高內聚、低耦合-解決MVC中View依賴Model的問題</td><td valign="top" width="365" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">高內聚、低耦合-解決winform中存在的問題。解決view和Model之間的依賴,屏蔽view改變帶來的影響。</td></tr><tr style="margin:0px; padding:0px"><td valign="top" width="95" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">應用場景?<br style="margin:0px; padding:0px"/></td><td valign="top" width="270" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">前端與后端交互架構設計(CS或BS)</td><td valign="top" width="281" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">前端與后端交互架構設計(CS或BS)</td><td valign="top" width="365" style="margin:0px; padding:3px; border:1px solid rgb(192,192,192); border-collapse:collapse; word-break:normal!important">前端與后端交互架構設計-WPF或Web通過js實現</td></tr></tbody></table>
##五、結束語
?
?????? 通過上面軟件架構模式的介紹,大家對這些軟件架構的模式有了一定的了解,后面的關于分層中篇、后篇就是結合一些具體的案例來進行代碼的編寫的講解和實現。當然如果大家有比較感興趣的議題,也請提出來,可以根據這些議題,然后將上面介
紹的這些模式來去實現。
????? 也歡迎大家針對我提出的這些思路進行討論,提出不同的看法和想法,另如果需要更深層次的討論,可以QQ與我聯系。
????? 關于上面介紹的只寫架構模式,我已經全部實現,如果需要相關的技術支持,請找我,或者您有什么建議或意見,都請聯系我。