2016-08-28 38 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)我想你可以从我提供的描述中得到答案。