【问题标题】:what is the need of Adapter Design pattern?适配器设计模式需要什么?
【发布时间】:2016-08-28 07:06:24
【问题描述】:

在下面的适配器设计模式示例代码中,为什么引入了一个新类而不是在客户端使用多个接口?

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 会怎样?
  • 在哪种情况下我们需要适配器类?
  • 为什么不简单继承所需的类,而是创建这种模式来访问另一个类方法?

【问题讨论】:

    标签: c# asp.net .net design-patterns adapter


    【解决方案1】:

    有时您有一个无法更改的给定 API(旧版/外部库/等...),并且您希望让您的 classes 能够在不更改其代码的情况下使用该 API。

    假设您使用的 API 具有 ISomethingToSerialize

    public interface ISomethingToSerialize
    {
        object[] GetItemsToSerialize();
    }
    

    该 API 还有一个Serialize 函数:

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

    现在您的代码中有一个class,而您不想或无法更改它,我们称之为MyUnchangeableClass

    这个class 没有实现ISomethingToSerialize,但是您想使用API 对其进行序列化,因此您创建了实现ISomethingToSerializeAdapterClass,以允许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 的要求。

    【讨论】:

      【解决方案2】:

      你的想法完全错误。 VendorAdaptee 是生成数据的代码实例,而 ShoppingPortalClient 是想要使用它的代码。

      让我解释一下现实世界的情况。您正在实施商店,而其他人已经实施了一项服务,可为您提供有关其产品的数据(VendorAdaptee)。这样做的简单方法是简单地调用他们的方法并使用数据,对吗?但这是他们的服务,当您不想上传整个解决方案并发布新版本时,他们可能希望稍后更改它。因此,您需要一个适配器,以确保将数据以您需要的格式发送到您的真实代码,而您根本不关心您的地址、方法名或数据格式。供应商。


      关于您的问题:

      无论如何,继承都不是这样。从概念上讲,商店无论如何都不是供应商。考虑到代码,这两个中的任何一个都没有相似之处,并且行为完全不同。一个提供数据,另一个使用它。

      【讨论】:

        【解决方案3】:

        您使用适配器的主要原因是您不想弄乱的遗留代码 - 或者您不适合某个接口的第三方。

        还有其他原因,通常取决于您发现如何更容易开发以及使用适配器设计模式是否对您有意义。不过,我认为它在其他情况下不是很有用。

        【讨论】:

          【解决方案4】:

          首先,我也不认为这是Adapter 模式的好例子。当您不能在您的类(例如 B)中直接使用一种特定类型的类(例如 A)时,适配器模式非常有意义,而是您实现了另一个可以在您的类(B)中直接使用的类(例如 C)并且it(C)可以直接使用第一个(A)。

          你可能会问,B 不能直接使用 A 的例子有哪些。很少。

          • A 的方法不返回 B 理想需要的类型。
          • 因此,我们不会在 B 中添加 B 的转换需求。相反,我们让 C 负责为 B 做这件事。
          • B 包含 A 等可能看起来不自然。

          回到你的问题

          (1)问是有意义的,

          如果 ShoppingPortalClient 直接'使用' VendorAdaptee,该怎么办?

          因为是主类,所以作为demo使用,不展示结构。还有一点要补充,就是要调用另一个类的方法,除非有意义,否则不要继承。在这种情况下,组合是首选。对于为什么不“使用”的问题,假设它不能。但你宁愿问为什么不能。在这个例子中我可以给出的答案只是假设调用 Adaptee 是不自然的。这就是为什么我说这不是一个很好的例子。 :)

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-06-14
            • 2011-01-20
            • 2010-10-03
            • 1970-01-01
            • 1970-01-01
            • 2012-05-25
            相关资源
            最近更新 更多