国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

封裝的變化之排序算法中的封裝

2024-07-21 02:29:34
字體:
來源:轉載
供稿:網友
  設想這樣一個需求,我們需要為自己的框架提供一個負責排序的組件。目前需要實現的是冒泡排序算法和快速排序算法,根據“面向接口編程”的思想,我們可以為這些排序算法提供一個統一的接口isort,在這個接口中有一個方法sort(),它能接受一個object數組參數。對數組進行排序后,返回該數組。接口的定義如下:

public interface isort
{
 void sort(ref object[] besorted);
}

  其類圖如下:


  然而一般對于排序而言,排列是有順序之分的,例如升序,或者降序,返回的結果也不相同。最簡單的方法我們可以利用if語句來實現這一目的,例如在quicksort類中:

public class quicksort:isort
{
 private string m_sorttype;
 public quicksort(string sorttype)
 {
  m_sorttype = sorttype;
 }
 public void sort(ref object[] besorted)
 {
  if (m_sorttype.toupper().trim() == “ascending”)
  {
   //執行升序的快速排序;
  }
  else
  {
   //執行降序的快速排序;
  }
 }
}

  當然,我們也可以將string類型的sorttype定義為枚舉類型,減少出現錯誤的可能性。然而仔細閱讀代碼,我們可以發現這樣的代碼是非常僵化的,一旦需要擴展,如果要求我們增加新的排序順序,例如字典順序,那么我們面臨的工作會非常繁重。也就是說,變化產生了。通過分析,我們發現所謂排序的順序,恰恰是排序算法中最關鍵的一環,它決定了誰排列在前,誰排列在后。然而它并不屬于排序算法,而是一種比較的策略,后者說是比較的行為。

  如果仔細分析實現isort接口的類,例如quicksort類,它在實現排序算法的時候,需要對兩個對象作比較。按照重構的做法,實質上我們可以在sort方法中抽取出一個私有方法compare(),通過返回的布爾值,決定哪個對象在前,哪個對象在后。顯然,可能發生變化的是這個比較行為,利用“封裝抽象”的原理,就應該為該行為建立一個專有的接口icompare,然而分別定義實現升序、降序或者字典排序的類對象。


  我們在每一個實現了isort接口的類構造函數中,引入icompare接口對象,從而建立起排序算法與比較算法的弱耦合關系(因為這個關系與抽象的icompare接口相關),例如quicksort類:

public class quicksort:isort
{
 private icompare m_compare;
 public quicksort(icompare compare)
 {
  m_compare= compare;
 }
 public void sort(ref object[] besorted)
 {
  //實現略
  for (int i = 0; i < besorted.length - 1; i++)
  {
   if (m_compare.compare(besorted[i],besorted[i+1))
   {
    //略;
   }
  }
  //實現略
 }
}


  最后的類圖如下:


  通過對比較策略的封裝,以應對它的變化,顯然是stategy模式的設計。事實上,這里的排序算法也可能是變化的,例如實現二叉樹排序。由于我們已經引入了“面向接口編程”的思想,我們完全可以輕易的添加一個新的類binarytreesort,來實現isort接口。對于調用方而言,isort接口的實現,同樣是一個strategy模式。此時的類結構,完全是一個對擴展開發的狀態,它完全能夠適應類庫調用者新需求的變化。

  再以petshop為例,在這個項目中涉及到訂單的管理,例如插入訂單。考慮到訪問量的關系,petshop為訂單管理提供了同步和異步的方式。顯然,在實際應用中只能使用這兩種方式的其中一種,并由具體的應用環境所決定。那么為了應對這樣一種可能會很頻繁的變化,我們仍然需要利用“封裝變化”的原理,建立抽象級別的對象,也就是iorderstrategy接口:

public interface iorderstrategy
{
 void insert(petshop.model.orderinfo order);
}

  然后定義兩個類ordersynchronous和orderasynchronous。類結構如下:



  在petshop中,由于用戶隨時都可能會改變插入訂單的策略,因此對于業務層的訂單領域對象而言,不能與具體的訂單策略對象產生耦合關系。也就是說,在領域對象order類中,不能new一個具體的訂單策略對象,如下面的代碼:

iorderstrategy orderinsertstrategy = new ordersynchronous();

  在martin fowler的文章《ioc容器和dependency injection模式》中,提出了解決這類問題的辦法,他稱之為依賴注入。不過由于petshop并沒有使用諸如sping.net等ioc容器,因此解決依賴問題,通常是利用配置文件結合反射來完成的。在領域對象order類中,是這樣實現的:

public class order
{
 private static readonly iorderstategy orderinsertstrategy = loadinsertstrategy();
 private static iorderstrategy loadinsertstrategy()
 {
  // look up which strategy to use from config file
  string path = configurationmanager.appsettings["orderstrategyassembly"];
  string classname = configurationmanager.appsettings["orderstrategyclass"];

  // load the appropriate assembly and class
  return (iorderstrategy)assembly.load(path).createinstance(classname);
 }
}

  在配置文件web.config中,配置如下的section:

<add key="orderstrategyassembly" value="petshop.bll"/>
<add key="orderstrategyclass" value="petshop.bll.ordersynchronous"/>

  這其實是一種折中的service locator模式。將定位并創建依賴對象的邏輯直接放到對象中,在petshop的例子中,不失為一種好方法。畢竟在這個例子中,需要依賴注入的對象并不太多。但我們也可以認為是一種無奈的妥協的辦法,一旦這種依賴注入的邏輯增多,為給程序者帶來一定的麻煩,這時就需要一個專門的輕量級ioc容器了。

  寫到這里,似乎已經脫離了“封裝變化”的主題。但事實上我們需要明白,利用抽象的方式封裝變化,固然是應對需求變化的王道,但它也僅僅能解除調用者與被調用者相對的耦合關系,只要還涉及到具體對象的創建,即使引入了工廠模式,但具體的工廠對象的創建仍然是必不可少的。那么,對于這樣一些業已被封裝變化的對象,我們還應該充分利用“依賴注入”的方式來徹底解除兩者之間的耦合。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泉州市| 新巴尔虎右旗| 桃园市| 都兰县| 赞皇县| 石河子市| 南康市| 根河市| 岳西县| 百色市| 中阳县| 青铜峡市| 连城县| 江津市| 莫力| 民县| 鹤岗市| 松桃| 宜良县| 宜兰市| 北碚区| 郓城县| 绿春县| 普兰店市| 大邑县| 土默特右旗| 江门市| 旬邑县| 博湖县| 娄烦县| 阿拉善右旗| 香河县| 滨海县| 兴城市| 赞皇县| 邵武市| 敦煌市| 乃东县| 黑河市| 阜南县| 垫江县|