系統架構技能之設計模式—適配器模式

作者: CallHot  來源: 博客園  發布時間: 2010-12-21 16:21  閱讀: 2590 次  推薦: 0   原文鏈接   [收藏]  

  一、上篇回顧

  通過上篇的簡單講解,我們知道了,組合模式意圖是通過整體與局部之間的關系,通過樹形結構的形式進行組織復雜對象,屏蔽對象內部的細節,對外展現統一的方式來操作對象,是我們處理更復雜對象的一個手段和方式。本文以查詢控件為例,說明了,查詢控件內部的組成元素,及如何操作內部的組成元素,包括添加元素,刪除和處理相應事件的Handler,當然組合模式的作用遠比這些強大,后面我們肯定會在一些實例代碼中運用到組合模式的。組合模式如果在條件允許的情況下,我們盡量使用組合模式來處理復雜對象,遠比通過繼承出來的對象來的有效。

  組合模式-強調的是如何組織整體和局部之間的結構,將整體和局部之間的關系,通過樹形這樣的結構來組織這種對象組合的結構關系。

  組合模式的適用場景:

  1、我們期望操作一個復雜對象和操作一個組成這個復雜對象內部的簡單對象一樣操作的時候,我們可以考慮對象組合。

  2、當一個對象由多個簡單對象組成,并且它又可能是其他對象的一個組成部分,這種情況下,組合模式是比較好的選擇。

  二、摘要

  本篇將會講述結構型模式中的經典模式-適配器模式,也是項目中經常使用的模式之一,我們現在開發一個系統的時候,也許會遇到各式各樣的要求,我們要求和現有的系統進行集成,或者是我們直接開發一個系統,或者是我們修改已有的系統達到滿足現有需求的要求。因此一般來說,每種情況,我們都有自己的應對方案。我們來看看項目中的幾種可能情況:

image

  通過上面的幾種情況,我們知道,開發一個新系統吧,成本和時間的投入較高,如果說我們舊系統目前運行的非常穩定,并且投入的成本非常高,我們既想繼續使用舊系統的功能,又想滿足新系統的需求,這個時候,我們怎么做呢?可能比較好的方式就是把舊系統通過適配器來轉換成新接口的調用形式,完成適配服務。當然本文也是主要針對這個思路,展開去講述適配器模式的一些用法,當然我這里可能講解了適配器模式的一些普遍用法,還有一些比較特殊的用法,需要大家多多指出,向大伙學習了。

  本文主要講述下面的幾個部分的內容:

  1、適配器模式的使用場景。

  2、適配器模式的經典實現。

  3、多適配器的封裝。

  4、其他情況的考慮。

  三、本文大綱

  a、上篇回顧。

  b、摘要。

  c、本文大綱。

  d、適配器模式的特點及使用場景。

  e、適配器模式的經典實現。

  f、適配器模式的其他方案。

  g、適配器模式使用總結。

  四、適配器模式的特點及使用場景

  4.1、適配器模式的特點

  適配器模式主要解決的問題就是我們要調用的接口類型,無法滿足我們新系統的使用需求,這時候,我們需要將舊系統的接口,通過適配器進行轉配,達到支持新接口調用的目的。對于這樣的要求,我們通過適配器就可以完成,當然如果有多個接口需要轉配,那么我們就需要為每一個接口提供一個適配器去完成轉換的工作。當然具體的調用過程,我們可以進行相應的封裝。達到比較通用的方式去調用適配器,完成適配服務。我們來看看適配的過程。        image  上圖基本給出了適配器的基本轉換的過程。

  4.2、適配器模式的場景

  我們根據上面的適配器的特點的介紹中,我們來分析下適配器模式的幾類比較適用的使用場景:

  1、我們在使用第三方的類庫,或者說第三方的API的時候,我們通過適配器轉換來滿足現有系統的使用需求。

  2、我們的舊系統與新系統進行集成的時候,我們發現舊系統的數據無法滿足新系統的需求,那么這個時候,我們可能需要適配器,完成調用需求。

  3、我們在使用不同數據庫之間進行數據同步。(我這里只是分析的是通過程序來說實現的時候的情況。還有其他的很多種方式[數據庫同步])。

  五、適配器模式的經典實現

  我們本節給出適配器模式的經典實現代碼,我們這里結合項目中的查詢服務來進行說明,舊系統中提供一個查詢服務方法Query();但是我新系統定義底層的數據訪問服務層的時候,卻是使用的GetList()方法,并且將之前的返回結果集合進行包裝成泛型的形式來進行。我們這里給出相關的示例代碼,大家就能清楚這個使用過程了,當然我們這里給出類適配器和對象適配器2種實現的方式,通過不同的實現思路,我們最后總結下,這2種形式的優缺點:

  1、類適配器

  針對上面描述的接口的轉配過程,我們給出示例代碼:

 
舊系統的查詢服務:
public class Query :IQuery
{

public object Query()
{

return new object();
}
}
新系統的查詢服務接口:

public interface ISelect
{

object GetList();
}
通過類適配器完成轉配操作:

public class QueryAdapter : Query, ISelect
{

public object GetList()
{

return base.Query();
}
}
具體的調用測試代碼如下:

class Program
{

static void Main(string[] args)
{
ISelect adapter
= new QueryAdapter();
object o= adapter.GetList();
System.Threading.Thread.Sleep(
10000);

}
}

  2、對象適配器

 
舊系統的查詢服務:
public class Query :IQuery
{

public object Query()
{

return new object();
}
}
新系統的查詢服務接口:

public interface ISelect
{

object GetList();
}
通過類適配器完成轉配操作:

public class QueryAdapter : ISelect
{

private Query query = new Query();

public object GetList()
{

return query.Query();
}
}
具體的調用測試代碼如下:

class Program
{

static void Main(string[] args)
{
ISelect adapter
= new QueryAdapter();
object o= adapter.GetList();
System.Threading.Thread.Sleep(
10000);
}
}

  上面我們就完成了經典的適配器模式的簡單實現,當然上面也沒有考慮通用性等各方面的內容,只是給出了一個大概的實現,當然對于上面的適配器的創建過程,我們可以通過前面講述的創建型模式中的幾個實現方案,進行相應的改進。

  六、適配器模式的其他方案

  上面給出了適配器模式的經典實現,參考其他篇講述的方式,我們給出適配器模式的其他演變方式

  6.1、批量適配器的封裝

  我們在項目中,可能需要對一批的舊系統的接口進行封裝,這個時候我們可以通過配置文件的方式配置適配器。

  例如我們上面的查詢,可能我現在對于XML文件的查詢方法與數據庫的查詢方法2個舊的查詢服務進行封裝,然后我在實際的項目中,通過配置來選擇我使用哪個查詢方法完成查詢服務,通過傳入參數,或者是配置節信息來進行控制。我們來看看相關的示例代碼:

 
舊系統定義的查詢服務接口:
public interface IQuery
{

object Query();
}
XML查詢和數據庫方式的實現:

public class XMLQuery : IQuery
{

public object Query()
{

throw new NotImplementedException();
}
}

public class DbQuery : IQuery
{

public object Query()
{

throw new NotImplementedException();
}
}
新查詢服務接口:

public interface ISelect
{

object GetList();
}
具體的適配器代碼實現:

public class XMLAdapter : ISelect
{

private XMLQuery query = new XMLQuery();
public object GetList()
{

return query.Query();
}
}

public class DbAdapter : ISelect
{

private DbQuery query = new DbQuery();
public object GetList()
{

return query.Query();
}
}
工廠來負責創建舊系統接口的服務的對象:

public class AdapterFactory
{

public static ISelect CreateAdapter()
{

return (ISelect)Activator.CreateInstance(Type.GetType(""));
}
}
具體的調用測試代碼:

class Program
{

static void Main(string[] args)
{
ISelect select
= AdapterFactory.CreateAdapter();
object o= select.GetList();
}
}

  6.2、通用適配器

 
舊系統定義的查詢服務接口:
public interface IQuery
{

object Query();
}
XML查詢和數據庫方式的實現:

public class XMLQuery : IQuery
{

public object Query()
{

throw new NotImplementedException();
}
}

public class DbQuery : IQuery
{

public object Query()
{

throw new NotImplementedException();
}
}
工廠來負責創建舊系統接口的服務的對象:

public class OldFactory
{

public static IQuery CreateQuery()
{

return (IQuery)Activator.CreateInstance(Type.GetType(""));
}
}
新查詢服務接口:

public interface ISelect
{

object GetList();
}
具體的通用適配器代碼實現:

public class ComAdapter : ISelect
{
IQuery query
= OldFactory.CreateQuery();

public object GetList()
{

return query.Query();
}
}
將適配器的創建過程通過工廠來實現,達到解耦的目的:

public class AdapterFactory
{

public static ISelect CreateAdapter()
{

return new ComAdapter ();
}
}
具體的調用測試代碼:

class Program
{

static void Main(string[] args)
{
ISelect select
= AdapterFactory.CreateAdapter();
object o= select.GetList();
}
}

  七、適配器模式使用總結

  我們上面給出了適配器模式的簡單講解,其實適配器模式的應用還是很廣泛的,上面也分析了適配器模式的使用場景和特點,那么其實本篇還沒有給出實例講述適配器之間的轉換:         

  上面我們講述了2中比較通用的形式來調用適配器,還有其他的方式,比如通過字典的方式,然后通過屬性索引的形式來使用適配器,我上面給出了一些比較簡單的通用的使用思路,當然還有很多更好的方式,希望大家指出,向大伙學習了。我們這里給出適配器之間相互轉換的情況,有的時候,我們發現2個適配器之間也需要進行相應的轉配,例如我們上面的數據庫和XML文件的查詢接口,例如有的時候,我需要把XML文件的數據轉換到數據庫中,或者把數據庫中的數據保存成XML形式,這個時候,我們就需要定義一個對象,來完成相應的適配器之間的適配。

image  通過轉配器來完成適配器到適配器之間的轉換。具體的代碼實現,這里暫不給出了,下篇會講橋模式的時候,會給出這部分的具體實現,還請關注!我相信通過上面的講述,大家對這個適配器模式有了一定的映像,我們上面沒有講述類適配器和對象適配器之間的區別,這里補充講解一下:

  對象適配器:不是通過繼承的方式,而是通過對象組合的方式來進行處理的,我們只要學過OO的設計原則的都知道,組合相比繼承是推薦的方式。

      類適配器:通過繼承的方式來實現,將舊系統的方法進行封裝。對象適配器在進行適配器之間的轉換過程中,無疑類適配器也能完成,但是依賴性會加大,并且隨著適配要求的靈活性,可能通過繼承膨脹的難以控制。

      一般來說類適配器的靈活性較差,對象適配器較靈活,是我們推薦的方式,可以通過依賴注入的方式,或者是配置的方式來做。類適配器需要繼承自要適配的舊系統的類,無疑這不是一個好的辦法。

  本文Demo下載

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()