2016-08-28 37 views
3

在下面的適配器設計模式示例代碼中,爲什麼引入一個新類而不是在客戶端使用多個接口?適配器設計模式的需求是什麼?

interface ITarget 
{ 
    List<string> GetProducts(); 
} 


public class VendorAdaptee 
{ 
    public List<string> GetListOfProducts() 
    { 
     List<string> products = new List<string>(); 
     products.Add("Gaming Consoles"); 
     products.Add("Television"); 
     products.Add("Books"); 
     products.Add("Musical Instruments"); 
     return products; 
    } 
} 


class VendorAdapter:ITarget 
{ 
    public List<string> GetProducts() 
    { 
     VendorAdaptee adaptee = new VendorAdaptee(); 
     return adaptee.GetListOfProducts(); 
    } 
} 


class ShoppingPortalClient 
{ 
    static void Main(string[] args) 
    { 
     ITarget adapter = new VendorAdapter(); 
     foreach (string product in adapter.GetProducts()) 
     { 
     Console.WriteLine(product); 
     } 
     Console.ReadLine(); 
    } 
} 

我對以上代碼有以下疑問。

  • 什麼,如果ShoppingPortalClient直接繼承VendorAdaptee?
  • 在哪種情況下我們需要適配器類?
  • 爲什麼不是簡單的繼承一個需要的類,創建這個模式來訪問另一個類方法?

回答

6

有時你有一個你不能改變的API(legacy/external-library/etc ...),你想讓你的classes能夠在不改變他們的代碼的情況下使用這個API。

比方說,你使用它有一個API的ISomethingToSerialize

​​

該API也有一個Serialize功能:

public class SerializationServices 
{ 
    byte[] Serialize(ISomethingToSerialize objectToSerialize); 
} 

現在,你必須在你的代碼class,而你沒有想要或不能夠改變它,我們稱之爲MyUnchangeableClass

class沒有實現ISomethingToSerialize,但要使用API所以你創建AdapterClass它們實現ISomethingToSerialize連載它允許MyUnchangeableClass使用它本身不實現它:

public class AdapterClass : ISomethingToSerialize 
{ 
    public AdapterClass(MyUnchangeableClass instance) 
    { 
     mInstance = instance; 
    } 

    MyUnchangeableClass mInstance; 

    public object[] GetItemsToSerialize() 
    { 
     return mInstance.SomeSpecificGetter(); 
    } 
} 

現在你可以使用

MyUnchangeableClass instance = ... //Constructor or factory or something... 
AdapterClass adapter = new AdapterClass(instance) 
SerializationServices.Serialize(adapter); 

序列化的MyUnchangeableClass一個實例,即使它本身不符合API的要求。

+0

感謝您的示例。它提供了一個更好的圖片.. – user1357872

2

您將使用適配器的主要原因是遺留的代碼,您不希望混淆 - 或者您不適合某個接口的第三方。

還有其他原因,通常取決於您如何更容易地開發以及如果使用適配器設計模式對您有意義。儘管如此,我不認爲它在其他情況下非常有用。

4

你的想法完全錯誤。 VendorAdaptee是生成數據的代碼實例,ShoppingPortalClient是想要使用它的人。

讓我來解釋一下真實世界的情況。您正在實施該商店,並且其他人已經實施了一項服務以向您提供有關其產品(VendorAdaptee)的數據。簡單的做法是簡單地調用他們的方法並使用數據,對吧?但是,這是他們的服務,他們可能希望稍後更改它,而不想上傳整個解決方案併發布新版本。因此,您需要一個適配器以確保數據將以您需要的格式發送到您的真實代碼,而您根本不在意您的地址,方法名稱或數據格式供應商。


關於你的問題:

繼承是不以任何方式的情況。從概念上講,一家商店並不是一個供應商。考慮到代碼,你在這兩者中沒有任何相似之處,而且行爲完全不同。一個是提供數據,另一個使用它。

2

首先我也不認爲這是Adapter模式的一個好例子。當你不能直接在你的類中使用某種類(比如說A)(比如說B)時,適配器模式是非常有意義的,相反,你需要實現另一個類(比如說C),它可以直接在你的類(B)它(C)可以直接使用第一個(A)。

你可能會問,什麼是B不能直接使用的例子。

  • A的方法不返回這是非常需要通過B.
  • 所以我們做的類型不搞砸了與B的內部B.加入轉換需要相反,我們給予責任到C做它B.
  • 它可能看起來不自然對於B包含A.等

回到你的問題

(1)如果你問這是有意義的,

什麼,如果ShoppingPortalClient直接'使用' VendorAdaptee?

僅僅因爲它是主類,它已被用作演示,而不是顯示結構。還有一件事要補充,就是因爲你想調用另一個類的方法,除非它有意義,否則不要繼承它。在這種情況下,組合是首選。對於這個問題,爲什麼不「使用」,只是假設它不能。但你問問爲什麼不能。我可以在這個例子中給出的答案只是假設調用Adaptee是不自然的。這就是爲什麼我說這不是一個好例子。 :)

(2),(3)我想你可以從我提供的描述中得到答案。