天天看點

系統架構師-基礎到企業應用架構-企業應用架構

      我們先來回顧下上篇講解的内容,我們前面的幾節分别講述了,業務邏輯層、資料通路層、服務層、表現層,我們了解了這些分層的職責和分層之間的大概的關聯

關系,本篇可能主要是簡單的介紹下企業應用的幾類模式,結合這幾個分層直接的互動來完成系統功能的建構。我們還是先對我們學習的四個分層的職責和功能做個大

概的回顧,我們先來看看下圖來回顧下我們講述的内容。

系統架構師-基礎到企業應用架構-企業應用架構

      我想通過上圖,大家能回憶起我們講述的相關内容,然後整理好自己的思路,我們本文将會針對這幾個分層進行相應的模式的講解,并且會結合執行個體來說明企業應

用架構的簡單應用。我想這也是大家關心的内容,我也希望大家能多提出寶貴意見,大家共同提高。

      之前說是提供PDF檔案的下載下傳的,以提供給需要學習的朋友更友善的形式,但是由于最近時間有限,沒能整理好,等過陣子提供一個完整的整合好的PDF版本,提

供給大家下載下傳,還望大家見諒。

      本篇我們将針對我們前面講述的幾個分層做個簡單的整合,就是通過一個簡單的執行個體代碼來說明下,我們給出的一個可能的企業應用架構模式去完成企業應用,并

且順帶分析下,企業應用中可能存在的瓶頸等,當然可能本章隻是點出一些概念,然後在後面的章節中去完成,比如我們的性能優化,性能瓶頸等,這些我們後面通過

這篇:系統架構師-基礎到企業應用架構-性能優化(架構瓶頸)(後續篇)詳細的分析。當然由于本章主要是基于前面講述的内容的一個整合和分析,可能部分觀點

還有更好的改進方案,還希望大家多提出寶貴意見和您的建議,謝謝!那麼我們先來看看我們本章講述的内容吧:

系統架構師-基礎到企業應用架構-企業應用架構

      本章主要講述下各分層之間的互動方式及可行的設計方案,并且分析我們在每個分層采用什麼樣的模式,及給出相應的示例代碼,當然這裡可能講述的不會是最好

的實作方案,還期待大家提出更好的改進方案。

      1、内容回顧

      2、開篇

      3、本文提綱

      4、企業應用架構執行個體

            4.1、企業應用架構中的實體分層

            4.2、資料通路層分析

            4.3、業務邏輯層分析

            4.4、服務層分析

            4.5、表現層分析

            4.6、分析總結

      5、結束語

      6、系列進度

      7、下篇預告

         4.1、企業應用架構的實體分層

      本節将會分層的相關介紹,并且分析分層的原因,為下篇:系統架構師-基礎到企業應用架構-分層[上篇] 做鋪墊。

     分層我想對大家來說都不會太陌生。因為我們平時在開發的過程中一般都是采用分層架構的方式,通過分層将系統的功能進行劃分,我們将系

統中的若幹有共同特征的部分放在一個分層中,然後通過分層之間的互動去完成系統的功能。

     我們看看企業應用的幾種應用程式模式:

系統架構師-基礎到企業應用架構-企業應用架構

    1、單擊應用程式就是一些本地服務的應用程式,這個應該沒啥特别的難度,例如Office應用程式,當然現在有線上版本的Office,這個應用的太多了。

    2、用戶端/伺服器的形式,特别是在WinForm、WPF、SilverLight方面的應用等,例如我們的常用的OutLook,雖然不是采用.NET平台開發的,但是原理一樣就

是通過用戶端通過通信服務來通路伺服器,然後取回相應的郵件資訊傳回給用戶端,相當于我們通過用戶端的形式來通路Web服務。

    3、Web服務:通過将開發的Web伺服器部署在伺服器上,然後我們就可以通過輸入HTTP網址的形式來通路web服務,我們這裡是通過浏覽器來完成的,其實這個

模式也是用戶端/伺服器的形式。隻不過這時的用戶端變成浏覽器+服務頁面,然後通過浏覽器來完成Web服務的通路。

    4、其他服務:我們這裡主要是針對一些其他的裝置,例如通信裝置等方面的通路,比如說我們現在提供一個衛星定位的服務,那麼通過裝置調用服務來完成,告知

使用者的GPS定位資訊等。很多這個方面的應用。這個方向應該是未來的一個主流吧。

    我們上面簡單的講述了系統的實體分層的形式,那麼我們來看看如何對系統的功能進行分層,也就是我們下面要詳細講解的執行個體分析。

       4.2、資料通路層分析

     資料通路層我們知道是唯一一個可以與資料庫之間直接進行互動的分層,資料通路層必須滿足的幾個功能和職責,我們這裡就不複述了,我們本篇可能就是直接給

出資料通路層的相關實作,并且分析出資料通路層與其他層之間的互動。

系統架構師-基礎到企業應用架構-企業應用架構

      我這裡的資料通路層提供所有的資料庫通路服務。我們來看看基本的服務功能吧

      我們這裡定義了一個DDL語句操作的枚舉,CUD的枚舉,因為我們提供了一個統一的資料通路服務,通過Excute來完成。

<code>/// &lt;summary&gt;</code>

<code>/// 資料通路操作類型</code>

<code>/// &lt;/summary&gt;</code>

<code>public</code> <code>enum</code> <code>DDLType</code>

<code>{</code>

<code>    </code><code>Create,</code>

<code>    </code><code>Update,</code>

<code>    </code><code>Delete</code>

<code>}</code>

     這裡用枚舉來定義資料庫字段與查詢條件值之間的關系

<code>/// 資料字段與字段值之間的關系表達式</code>

<code>public</code> <code>enum</code> <code>FieldExpressionType</code>

<code>    </code><code>EquleTo,</code>

<code>    </code><code>BeginThen,</code>

<code>    </code><code>LessThen,</code>

<code>    </code><code>BetweenAnd,</code>

<code>    </code><code>Like</code>

    我們再來看看我們定義的查詢條件的接口

<code>/// 定義子查詢接口</code>

<code>public</code> <code>interface</code> <code>ICondition</code>

<code>    </code><code>int</code> <code>Add(</code><code>string</code> <code>fieldName,</code><code>object</code> <code>value,FieldExpressionType fetType);</code>

<code>    </code><code>int</code> <code>Add(ICondition condition);</code>

<code>    </code><code>string</code> <code>WhereCondition;</code>

<code>    </code><code>string</code> <code>OrderCondition;</code>

    資料通路層接口代碼

<code>/// 定義統一的資料通路服務</code>

<code>public</code> <code>interface</code> <code>IDataAccess</code>

<code>    </code><code>#region CUD</code>

<code>    </code><code>int</code> <code>Create&lt;T&gt;(T item);</code>

<code>     </code><code>int</code> <code>Update&lt;T&gt;(T item);</code>

<code>     </code><code>int</code> <code>Delete&lt;T&gt;(T item);</code>

<code>     </code><code>int</code> <code>Execute&lt;T&gt;(T item,DDLType ddlType);</code>

<code>    </code><code>#endregion</code>

<code>    </code><code>#region Read服務</code>

<code>     </code><code>List&lt;T&gt; Query&lt;T&gt;(ICondition condition);</code>

<code>     </code><code>T GetModelByPrimaryKey&lt;T&gt;(</code><code>object</code> <code>key);</code>

<code>     </code><code>List&lt;T&gt; GetAll&lt;T&gt;();</code>

<code>     </code><code>#endregion</code>

<code>    </code><code>#region 事務操作</code>

<code>     </code><code>void</code> <code>BeginTransaction();</code>

<code>     </code><code>bool</code> <code>Commit();</code>

<code>     </code><code>bool</code> <code>RollBack();</code>

<code>     </code><code>bool</code> <code>IsTransaction;</code>

    我們知道具體的代碼我們是通過反射+特性的形式來完成資料庫操作語句的生成的,我們來看看可行的代碼,屬性項特性的定義。

<code>/// Model中的字段屬性特性</code>

<code>[AttributeUsage(AttributeTargets.All, AllowMultiple =</code><code>false</code><code>)]</code>

<code>public</code> <code>class</code> <code>PropertyAttribute : Attribute</code>

<code>    </code><code>private</code> <code>string</code> <code>dbColumnName;</code>

<code>    </code><code>private</code> <code>bool</code> <code>isPrimary;</code>

<code>    </code><code>private</code> <code>DbType dbType;</code>

<code>    </code><code>private</code> <code>object</code> <code>defaultValue;</code>

<code>    </code><code>private</code> <code>bool</code> <code>isIdentify;</code>

<code>    </code><code>private</code> <code>int</code> <code>length;</code>

<code>    </code><code>public</code> <code>string</code> <code>DbColumnName</code>

<code>    </code><code>{</code>

<code>        </code><code>get</code>

<code>        </code><code>{</code>

<code>            </code><code>return</code> <code>this</code><code>.dbColumnName;</code>

<code>        </code><code>}</code>

<code>        </code><code>set</code>

<code>            </code><code>this</code><code>.dbColumnName = value;</code>

<code>    </code><code>}</code>

<code>    </code><code>public</code> <code>bool</code> <code>IsPrimary</code>

<code>            </code><code>return</code> <code>this</code><code>.isPrimary;</code>

<code>            </code><code>this</code><code>.isPrimary = value;</code>

<code>    </code><code>public</code> <code>bool</code> <code>IsIdentify</code>

<code>            </code><code>return</code> <code>this</code><code>.isIdentify;</code>

<code>            </code><code>this</code><code>.isIdentify = value;</code>

<code>    </code><code>public</code> <code>DbType DbType</code>

<code>            </code><code>return</code> <code>this</code><code>.dbType;</code>

<code>            </code><code>this</code><code>.dbType = value;</code>

<code>    </code><code>public</code> <code>object</code> <code>DefaultValue</code>

<code>            </code><code>return</code> <code>this</code><code>.defaultValue;</code>

<code>            </code><code>this</code><code>.defaultValue = value;</code>

<code>    </code><code>public</code> <code>int</code> <code>DbLength</code>

<code>            </code><code>return</code> <code>this</code><code>.length;</code>

<code>            </code><code>this</code><code>.length = value;</code>

<code>    </code><code>public</code> <code>PropertyAttribute(</code><code>string</code> <code>dbName,</code><code>bool</code> <code>isPrimery, DbType type,</code><code>object</code> <code>dValue)</code>

<code>        </code><code>this</code><code>.dbColumnName = dbName;</code>

<code>        </code><code>this</code><code>.isPrimary = isPrimery;</code>

<code>        </code><code>this</code><code>.dbType = type;</code>

<code>        </code><code>this</code><code>.defaultValue =</code><code>this</code><code>.GetDefaultValue();</code>

<code>    </code><code>private</code> <code>object</code> <code>GetDefaultValue()</code>

<code>        </code><code>return</code> <code>new</code> <code>object</code><code>();</code>

<code>    </code><code>public</code> <code>PropertyAttribute(</code><code>string</code> <code>dbName)</code>

<code>        </code><code>this</code><code>.isPrimary =</code><code>false</code><code>;</code>

<code>        </code><code>this</code><code>.dbType = DbType.String;</code>

<code>    </code><code>public</code> <code>PropertyAttribute(</code><code>string</code> <code>dbName,</code><code>bool</code> <code>isPrimery)</code>

<code>    </code><code>public</code> <code>PropertyAttribute(</code><code>string</code> <code>dbName,</code><code>bool</code> <code>isPrimery, DbType type)</code>

<code>        </code><code>this</code><code>.defaultValue =</code><code>null</code><code>;</code>

    我們再來看看基于表上的特性

<code> </code><code>/// 基于表的自定義特性類</code>

<code> </code><code>/// &lt;/summary&gt;</code>

<code>public</code> <code>class</code> <code>TableAttribute : Attribute</code>

<code> </code><code>{</code>

<code>     </code><code>private</code> <code>string</code> <code>dbTableName;</code>

<code>     </code><code>public</code> <code>TableAttribute(</code><code>string</code> <code>dbName)</code>

<code>     </code><code>{</code>

<code>         </code><code>this</code><code>.dbTableName = dbName;</code>

<code>     </code><code>}</code>

<code>     </code><code>public</code> <code>string</code> <code>TableName</code>

<code>         </code><code>get</code>

<code>         </code><code>{</code>

<code>             </code><code>return</code> <code>this</code><code>.dbTableName;</code>

<code>         </code><code>}</code>

<code>         </code><code>set</code>

<code>             </code><code>this</code><code>.dbTableName = value;</code>

<code> </code><code>}</code>

<code>     </code><code>根據反射取出表名</code>

<code>     </code><code>/// &lt;summary&gt;</code>

<code>     </code><code>/// 傳回Model對應的資料庫表名</code>

<code>     </code><code>/// &lt;/summary&gt;</code>

<code>     </code><code>/// &lt;typeparam name="T"&gt;&lt;/typeparam&gt;</code>

<code>     </code><code>/// &lt;param name="model"&gt;&lt;/param&gt;</code>

<code>     </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code>     </code><code>public</code> <code>string</code> <code>DbTableName&lt;T&gt;(T model)</code>

<code>         </code><code>string</code> <code>dbName =</code><code>string</code><code>.Empty;</code>

<code>         </code><code>DPM.Common.TableAttribute attr =</code><code>null</code><code>;</code>

<code>         </code><code>object</code><code>[] attributes = model.GetType().GetCustomAttributes(</code><code>typeof</code><code>(DPM.Common.TableAttribute),</code><code>true</code><code>);</code>

<code>         </code><code>if</code> <code>(attributes.Length &gt; 0)</code>

<code>             </code><code>attr = (DPM.Common.TableAttribute)attributes[0];</code>

<code>         </code><code>if</code> <code>(attr !=</code><code>null</code><code>)</code>

<code>             </code><code>dbName = attr.TableName;</code>

<code>         </code><code>return</code> <code>dbName;</code>

<code>     </code><code>根據反射取出表中的列</code>

<code>    </code><code>/// &lt;summary&gt;</code>

<code>    </code><code>/// 動态建立表中字段清單</code>

<code>    </code><code>/// &lt;/summary&gt;</code>

<code>    </code><code>/// &lt;typeparam name="T"&gt;&lt;/typeparam&gt;</code>

<code>    </code><code>/// &lt;param name="model"&gt;&lt;/param&gt;</code>

<code>    </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code>    </code><code>public</code> <code>string</code> <code>InitDbColumns&lt;T&gt;(T model)</code>

<code>        </code><code>StringBuilder commandBuilder =</code><code>new</code> <code>StringBuilder();</code>

<code>        </code><code>DPM.Common.PropertyAttribute attr =</code><code>null</code><code>;</code>

<code>        </code><code>foreach</code> <code>(PropertyInfo property</code><code>in</code> <code>model.GetType().GetProperties())</code>

<code>            </code><code>object</code><code>[] attributes = property.GetCustomAttributes(</code><code>typeof</code><code>(DPM.Common.PropertyAttribute),</code><code>true</code><code>);</code>

<code>            </code><code>if</code> <code>(attributes.Length &gt; 0)</code>

<code>            </code><code>{</code>

<code>                </code><code>attr = (DPM.Common.PropertyAttribute)attributes[0];</code>

<code>            </code><code>}</code>

<code>            </code><code>if</code><code>(commandBuilder.length&gt;0)</code>

<code>                  </code><code>commandBuilder.Append(“,”);</code>

<code>            </code><code>commandBuilder.Append(attr.DbColumnName);</code>

<code>        </code><code>return</code> <code>commandBuilder.ToString();</code>

       當然這裡隻是給出了簡單的示例,我們來看看生成的Insert 語句的格式吧

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

<code>  </code><code>/// &lt;summary&gt;</code>

<code>  </code><code>/// 動态建立表中字段更新清單</code>

<code> </code><code>/// &lt;typeparam name="T"&gt;&lt;/typeparam&gt;</code>

<code> </code><code>/// &lt;param name="model"&gt;&lt;/param&gt;</code>

<code> </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code> </code><code>public</code> <code>string</code> <code>InitInsertColumns&lt;T&gt;(T model)</code>

<code>     </code><code>StringBuilder filedBuilder =</code><code>new</code> <code>StringBuilder();</code>

<code>     </code><code>StringBuilder valueBuilder =</code><code>new</code> <code>StringBuilder();</code>

<code>     </code><code>StringBuilder commandBuilder =</code><code>new</code> <code>StringBuilder();</code>

<code>     </code><code>DPM.Common.PropertyAttribute attr =</code><code>null</code><code>;</code>

<code>     </code><code>foreach</code> <code>(PropertyInfo property</code><code>in</code> <code>model.GetType().GetProperties())</code>

<code>         </code><code>object</code><code>[] attributes = property.GetCustomAttributes(</code><code>typeof</code><code>(DPM.Common.PropertyAttribute),</code><code>true</code><code>);</code>

<code>             </code><code>attr = (DPM.Common.PropertyAttribute)attributes[0];</code>

<code>         </code><code>if</code> <code>(attr.DbColumnName ==</code><code>""</code><code>)</code>

<code>             </code><code>continue</code><code>;</code>

<code>         </code><code>if</code> <code>(attr.IsIdentify)</code>

<code>         </code><code>if</code> <code>(filedBuilder.Length &gt; 0)</code>

<code>             </code><code>filedBuilder.Append(</code><code>","</code> <code>+ attr.DbColumnName);</code>

<code>             </code><code>valueBuilder.Append(</code><code>","</code> <code>+ property.GetValue(model,</code><code>null</code><code>));</code>

<code>         </code><code>else</code>

<code>             </code><code>filedBuilder.Append(attr.DbColumnName);</code>

<code>             </code><code>valueBuilder.Append(property.GetValue(model,</code><code>null</code><code>));</code>

<code>     </code><code>commandBuilder.Append(SqlDMLText.LKH);</code>

<code>     </code><code>commandBuilder.Append(filedBuilder.ToString());</code>

<code>     </code><code>commandBuilder.Append(SqlDMLText.RKH);</code>

<code>     </code><code>commandBuilder.Append(SqlDMLText.VALUES);</code>

<code>     </code><code>commandBuilder.Append(valueBuilder.ToString());</code>

<code>     </code><code>return</code> <code>commandBuilder.ToString();</code>

       其他的語句類似了,這部分詳細的代碼我們會在ORM篇詳細的講述,并且對反射的性能通過優化來提供性能。

       我們來總結下資料通路層應該有的功能吧。我認為應該提供以下的功能

系統架構師-基礎到企業應用架構-企業應用架構

了,我們接下來講講業務邏輯層吧。

          4.3、業務邏輯層分析

      上篇我們貼出來了一些比較典型的資料通路層的代碼,當然沒有上全部的代碼,本文将會提供demo執行個體下載下傳,大家可以參考其中的部分代碼。我們來看看業務層

中的每個業務對象應該具有什麼樣的智能呢?我們知道我們這裡不建議業務對象直接來通路資料通路層,那麼我們如何實作持久化透明的方式呢?我記得之前我講述業

務邏輯層的時候也提到這個方面的要求了,還有不少熱心的園友問我如何實作,我這裡給出幾個可能的辦法,當然如果有更好的辦法,還請大家多多提出。我這裡給出

個簡單的業務對象的職責,當然我這裡給出的職責是我了解的在我的這個執行個體中業務對象應該具有的職責。

      接下來我們看看業務邏輯層的職責吧,然後我們給出示例代碼

系統架構師-基礎到企業應用架構-企業應用架構

      我們來舉例說明一個業務對象可能具有的功能吧?我們這裡以還是以B2C系統為例吧,我們來說說訂單的可能行為吧:

<code>/// 訂單</code>

<code> </code><code>public</code> <code>class</code> <code>Order</code>

<code>     </code><code>/// 産品清單</code>

<code>     </code><code>private</code> <code>List&lt;Product&gt; products =</code><code>new</code> <code>List&lt;Product&gt;();</code>

<code>     </code><code>/// 擷取訂單的金額</code>

<code>     </code><code>/// &lt;param name="order"&gt;&lt;/param&gt;</code>

<code>     </code><code>public</code> <code>decimal</code> <code>GetOrderCount(Model.Order order)</code>

<code>         </code><code>decimal</code> <code>totalCount = 0;</code>

<code>         </code><code>foreach</code> <code>(Product product</code><code>in</code> <code>products)</code>

<code>             </code><code>totalCount += product.Cash;</code>

<code>         </code><code>return</code> <code>totalCount;</code>

<code>     </code><code>/// 擷取該訂單下的所有産品</code>

<code>     </code><code>public</code> <code>List&lt;Product&gt; GetProduct(Model.Order order)</code>

<code>         </code><code>return</code> <code>new</code> <code>List&lt;Product&gt;();</code>

     當然這裡面的取得與訂單相關的産品清單,因為我們沒有設計在DTO中預設包含這個屬性,那麼我們這裡其實可以考慮增加延遲加載的形式,一旦加載後,也可以

第一次加載後,緩存起來,下次使用的過程中直接取出來。

      我們來看看與這個訂單業務邏輯相關的服務層代碼

<code>/// 訂單服務</code>

<code>public</code> <code>class</code> <code>OrderService</code>

<code>    </code><code>private</code> <code>List&lt;Model.Product&gt; products =</code><code>new</code> <code>List&lt;Model.Product&gt;();</code>

<code>    </code><code>/// 持久化透明的方式</code>

<code>    </code><code>/// &lt;param name="order"&gt;&lt;/param&gt;</code>

<code>    </code><code>/// &lt;param name="type"&gt;&lt;/param&gt;</code>

<code>    </code><code>public</code> <code>int</code> <code>Execute(Model.Order order,DAL.DDLType type)</code>

<code>        </code><code>return</code> <code>DAL.SQLServer.Instance.Execute(order, type);</code>

<code>    </code><code>/// 擷取訂單的總金額</code>

<code>    </code><code>public</code> <code>decimal</code> <code>GetOrderCash(Model.Order order)</code>

<code>        </code><code>BLL.Order =</code><code>new</code> <code>BLL.Order(order);</code>

<code>        </code><code>return</code> <code>order.GetOrderCount();</code>

<code>    </code><code>/// 儲存訂單資訊</code>

<code>    </code><code>public</code> <code>int</code> <code>SaveOrder(Model.Order order, DAL.DDLType type)</code>

<code>        </code><code>int</code> <code>iAff = 0;</code>

<code>        </code><code>//将與訂單相關的産品資訊也同步進行儲存。</code>

<code>        </code><code>//我們這裡通過事務的方式進行處理</code>

<code>        </code><code>try</code>

<code>            </code><code>DAL.SQLServer.Instance.BeginTransaction();</code>

<code>            </code><code>//具體的邏輯</code>

<code>            </code><code>//插入産品資訊</code>

<code>            </code><code>foreach</code> <code>(Model.Product product</code><code>in</code> <code>products)</code>

<code>                </code><code>DAL.SQLServer.Instance.Create(product);</code>

<code>                </code><code>iAff++;</code>

<code>            </code><code>//插入訂單資訊</code>

<code>           </code><code>iAff+= DAL.SQLServer.Instance.Create(order);</code>

<code>            </code><code>DAL.SQLServer.Instance.Commit();</code>

<code>            </code><code>return</code> <code>iAff;</code>

<code>        </code><code>catch</code>

<code>            </code><code>DAL.SQLServer.Instance.RollBack();</code>

<code>            </code><code>return</code> <code>0;</code>

<code>        </code><code>finally</code>

<code>            </code><code>DAL.SQLServer.Instance.Dispose();</code>

      通過上面的代碼我們可以看出,目前的業務邏輯層中的業務對象隻是處理自身的相關業務邏輯,通過服務層與資料層進行互動,然後業務對象并不關系自身的

CRUD的業務,而是通過服務層來完成的,那麼對于CUD我想大家應該沒有什麼争議,因為持久化透明隻是說把業務邏輯層原本通過繼承或者是實作接口,或者依賴注

入的形式來完成持久化的操作。

      我們這裡則是将這樣的持久化操作提出來放在服務層來完成,這樣可以降低業務層與資料通路層的依賴,那麼大家肯定關心如何實作業務邏輯對象的查詢服務呢?

我的思路是這樣的,大家請看看是否合理,或者您有好的思路或者想法一定要告知我,不甚感激!

系統架構師-基礎到企業應用架構-企業應用架構

      不知道我們上面的上圖是否表述的很清楚,還請大家多多的批評指出。當然上述的模式,可能在實際的企業應用中還是有點困難的,還有一種業務邏輯層的持久化

透明實作。就是通過AOP來完成,或者是通過代理類來實作。這裡說心裡話,我對AOP的具體實作并沒有研究過,但是通過動态注入的方式的确可以實作這個功能。具

體的實作方式就交給大家來完成了。

       4.4服務層分析

      服務層作為協調業務對象進行相應的業務流的控制,當然服務層隻是協調業務對象之間的互動,并不是負責具體的業務邏輯,這裡的服務層應該是隻負責業務對象

之間的互動。當然我這裡還把部分對資料完整性,資料類型等方面的内容放在服務層來做。下面來說明服務層可能包含的功能:

系統架構師-基礎到企業應用架構-企業應用架構

      我們在業務邏輯層中也貼出了部分代碼。當然服務層中其實還可以有很多的内容,比如通過我們在前面的服務層講解時介紹的幾個模式,我們也都是可以在服務層

中應用的。當然我們這裡的執行個體代碼可能就不會貼出這幾個模式了,我們這裡舉例來說明服務層中的部分服務代碼。例如我們前面經常舉例說明的訂單管理中的提醒功

能。

      比如我們有時候我們的提醒功能,需要郵件提醒或者是短信提醒的幾種服務方式,這時候我們可以通過提供統一的服務接口,然後不需要單獨的在界面層去單獨的

定義,我們通過接口的形式為後期的變化友善擴充,我們來給出部分代碼:

49

50

51

52

53

54

55

56

57

58

59

60

<code>    </code><code>/// 提醒服務</code>

<code>    </code><code>public</code> <code>interface</code> <code>IAlarmService</code>

<code>        </code><code>/// &lt;summary&gt;</code>

<code>        </code><code>/// 發送消息的服務</code>

<code>        </code><code>/// &lt;/summary&gt;</code>

<code>        </code><code>/// &lt;param name="reciveObject"&gt;接收方&lt;/param&gt;</code>

<code>        </code><code>/// &lt;param name="title"&gt;标題&lt;/param&gt;</code>

<code>        </code><code>/// &lt;param name="content"&gt;消息内容&lt;/param&gt;</code>

<code>        </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code>        </code><code>bool</code> <code>SendMessage(</code><code>string</code> <code>reciveObject,</code><code>string</code> <code>title,</code><code>string</code> <code>content);</code>

<code>    </code><code>我們來看看郵件提醒服務的簡單實作代碼</code>

<code>public</code> <code>class</code> <code>EmailAlarm : IAlarmService</code>

<code>        </code><code>#region IAlarmService 成員</code>

<code>        </code><code>/// &lt;param name="strSmtpServer"&gt;郵件伺服器(如果是163郵箱就寫smtp.163.com)&lt;/param&gt;</code>

<code>        </code><code>/// strSmtpServer</code>

<code>        </code><code>/// &lt;param name="strFrom"&gt;發件人的帳号&lt;/param&gt;</code>

<code>        </code><code>/// strFrom</code>

<code>        </code><code>/// &lt;param name="strFromPass"&gt;發件人密碼&lt;/param&gt;</code>

<code>        </code><code>/// strFromPass</code>

<code>        </code><code>public</code> <code>bool</code> <code>SendMessage(</code><code>string</code> <code>reciveObject,</code><code>string</code> <code>title,</code><code>string</code> <code>content)</code>

<code>            </code><code>bool</code> <code>isSuccess =</code><code>true</code><code>;</code>

<code>            </code><code>MailSetting model = DAL.SQLServer.Instance.GetModelByPrimaryKey&lt;MailSetting&gt;();</code>

<code>            </code><code>try</code>

<code>                </code><code>System.Net.Mail.SmtpClient client =</code><code>new</code> <code>SmtpClient(model.strSmtpServer);</code>

<code>                </code><code>client.UseDefaultCredentials =</code><code>false</code><code>;</code>

<code>                </code><code>client.Credentials =</code><code>new</code> <code>System.Net.NetworkCredential(model.strFrom, model.strFromPass);</code>

<code>                </code><code>client.DeliveryMethod = SmtpDeliveryMethod.Network;</code>

<code>                </code><code>System.Net.Mail.MailMessage message =</code><code>new</code> <code>System.Net.Mail.MailMessage(model.strFrom, reciveObject, title, content);</code>

<code>                </code><code>message.BodyEncoding = System.Text.Encoding.UTF8;</code>

<code>                </code><code>message.IsBodyHtml =</code><code>true</code><code>;</code>

<code>                </code><code>client.Send(message);</code>

<code>            </code><code>catch</code>

<code>                </code><code>isSuccess =</code><code>false</code><code>;</code>

<code>            </code><code>return</code> <code>isSuccess;</code>

<code>        </code><code>#endregion</code>

      短信服務也和郵件服務類似,通過實作接口來提供服務,那麼我們在比如說訂單,或者其他的可能會提醒的地方,就可以通過自定義實作不同的格式服務,來完成

調用。

       4.5、表現層分析

     我們都知道表現層是最終顯示與使用者互動的功能的,那麼我們的表現層是怎麼來調用服務層的呢?我們這裡的執行個體是采用服務層調用的方式來完成。我們這裡通過

定義接口的形式,然後通過實作不同的使用者UI,然後我們通過展示器來調用服務層,然後将服務層中的處理結果傳回給展示器,展示器與視圖之間進行互動,我們來看

看表現層的層級關系。

系統架構師-基礎到企業應用架構-企業應用架構

些都是有可能的,我們需要根據項目具體的情況去決定。

     我們來看看UI層的視圖代碼:

     我們在視圖中保持展示器的引用。

<code>/// 定義統一的視圖接口代碼</code>

<code>public</code> <code>interface</code> <code>IView</code>

<code>    </code><code>/// 展示器通路器</code>

<code>    </code><code>B2C.Presenter.IPresenter Presenter</code>

<code>        </code><code>get</code><code>;</code>

<code>        </code><code>set</code><code>;</code>

<code> </code><code>我們來看看展示器中的部分代碼</code>

<code>/// 展示器接口</code>

<code>public</code> <code>interface</code> <code>IPresenter</code>

<code>    </code><code>/// 重新生成視圖</code>

<code>    </code><code>string</code> <code>Review()</code>

<code>        </code><code>return</code> <code>string</code><code>.Empty;</code>

<code>    </code><code>/// 操作Model</code>

<code>    </code><code>/// &lt;param name="?"&gt;&lt;/param&gt;</code>

<code>    </code><code>T Controller&lt;T&gt;(T item);</code>

      視圖層通過依賴注入的方式,或者是屬性注入,還是實作接口的方式來實作展示器的引用,展示器提供接處理使用者操作的功能,然後根據處理後的結果決定是否刷

新視圖。

      當然如果你這裡是借助的MVC架構來實作的話,可能控制器中的代碼就要是通路服務層,或者業務邏輯層,資料通路層了,可能代碼的形式會有所不同。其實我們

還有更好的方式去實作視圖的展現。比如我們可以讓視圖層與XML檔案進行綁定的形式,展示器通過生成XML檔案,然後視圖層界面去解析這個XML檔案中的相應配

置,來完成展示,這樣的話,可能視圖層不需要處理單獨的代碼,而且視圖可以通過序列化與反序列化的形式,視圖的更改或者操作都可以有系統自動完成,而不需要

提供展示器來完成。當然這樣的形式僅限簡單的應用程式時,通過這樣的形式來處理可能會比較靈活。

       4.6、分析總結

      我們上面主要講述了企業架構中的一個可能的架構,當然這樣的架構不是最好的方案,還需要大家多多讨論和交流,我隻是根據自己的經驗,結合一些項目中的一

些問題進行了總結之後分析這樣的架構模式,還不知道在實際的姓名中是否能滿足适應性和很好的擴充性,這個還有待檢驗,我這裡并沒有給出完整的代碼實作,隻是

給出一種可能的架構模式的結構,具體的實作代碼還需要大家自己完善。

      我們總結下我們講述的内容:

      1、分析了四個層次中我們對于設計的考慮和各分層中職責和他們之間的互動,我這裡是通過實體層來處理DTO的。

      2、舉例給出部分代碼說明每個分層的職責并且分工要明确。

      3、表現層中與其他各層之間可能的互動關系。

      我想通過上面的可能的模式分析,給大家一個思路,讓大家通過這個思路有個更多的思考。

      本篇主要講述的是一個架構思路,給出的代碼可能不是完全的,隻是給了一個各層的大概的結構,因為要實作這樣的一個完整的執行個體demo,那是需要非常多的代

碼和要考慮的因素很多,本篇很多内容并沒有涵蓋,不過我想這樣的方式是不太好的,我後面會盡量将前面講過的内容,整理出來,以後講述執行個體的時候盡量就是一個

可以運作的demo執行個體。

前篇

      1、系統架構師-基礎到企業應用架構系列之--開卷有益

      2、系統架構師-基礎到企業應用架構-系統模組化[上篇]

      3、系統架構師-基礎到企業應用架構-系統模組化[中篇](上)

      4、系統架構師-基礎到企業應用架構-系統模組化[中篇](下)

      5、系統架構師-基礎到企業應用架構-系統模組化[下篇]

      6、系統架構師-基礎到企業應用架構-系統設計規範與原則[上篇]

      7、系統架構師-基礎到企業應用架構-系統設計規範與原則[下篇]

      8、系統架構師-基礎到企業應用架構-設計模式[上篇]

      9、系統架構師-基礎到企業應用架構-設計模式[中篇]

      10、系統架構師-基礎到企業應用架構-設計模式[下篇]

中篇

      11、系統架構師-基礎到企業應用架構-企業應用架構

      12、系統架構師-基礎到企業應用架構-分層[上篇]

      13、系統架構師-基礎到企業應用架構-分層[中篇]

      14、系統架構師-基礎到企業應用架構-分層[下篇]

      15、系統架構師-基礎到企業應用架構-表現層

      16、系統架構師-基礎到企業應用架構-服務層

      17、系統架構師-基礎到企業應用架構-業務邏輯層

      18、系統架構師-基礎到企業應用架構-資料通路層

      19、系統架構師-基礎到企業應用架構-元件服務

      20、系統架構師-基礎到企業應用架構-安全機制

後篇

      21、單機應用、用戶端/伺服器、多服務、企業資料總線全解析

      22、系統架構師-基礎到企業應用架構-單機應用(執行個體及demo)

      23、系統架構師-基礎到企業應用架構-用戶端/伺服器(執行個體及demo)

      24、系統架構師-基礎到企業應用架構-多服務(執行個體及demo)

      25、系統架構師-基礎到企業應用架構-企業資料總線(執行個體及demo)

      26、系統架構師-基礎到企業應用架構-性能優化(架構瓶頸)

      27、系統架構師-基礎到企業應用架構-完整的架構方案執行個體[上篇]

      28、系統架構師-基礎到企業應用架構-完整的架構方案執行個體[中篇]

      29、系統架構師-基礎到企業應用架構-完整的架構方案執行個體[下篇]

      30、系統架構師-基礎到企業應用架構-總結及後續

七、下篇預告

      下一篇我們将會開始講解系統架構中的分層-上-中-下進行相關讨論及設計方案分析,這些都是本人在工作中的經驗總結,由于本人能力有限,不足之處,

還請大家多多指出。希望大家持續關注!

本文轉自何戈洲部落格園部落格,原文連結:http://www.cnblogs.com/hegezhou_hot/archive/2010/10/17/1853909.html,如需轉載請自行聯系原作者