适配器设计模式的需求是什么?

本文关键字:是什么 需求 设计模式 适配器 | 更新日期: 2023-09-27 18:04:16

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

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

适配器设计模式的需求是什么?

有时你有一个给定的API,你不能改变(遗留/外部库/等…),你想让你的classes能够使用该API而不改变他们的代码。

假设你使用的API有一个ISomethingToSerialize

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

该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的要求。

你完全搞错了。VendorAdaptee是生成数据的代码实例,ShoppingPortalClient是想要使用数据的对象。

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


关于你的问题:

继承在任何方面都不是这种情况。从概念上讲,商店在任何方面都不是供应商。考虑到代码,这两者中没有任何相似之处,而且行为完全不同。一个是提供数据,另一个是使用数据。

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

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

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

你可能会问,B不能直接使用a的例子有哪些?

  • A的方法没有返回b理想需要的类型。
  • 所以我们不要把B的转换需求添加到B中,而是把责任交给C来为B做。
  • B中含有a等可能看起来不自然

回到你的问题

如果你问,这是有意义的,

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

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

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