简体   繁体   English

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

[英]what is the need of Adapter Design pattern?

In the below adapter design pattern sample code, why a new class is introduced instead of using multiple interface in the client? 在下面的适配器设计模式示例代码中,为什么要引入新类而不是在客户端中使用多个接口?

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();
   }
}

I have the below queries related to the above code. 我有以下与上述代码相关的查询。

  • What, if ShoppingPortalClient directly inherits VendorAdaptee? 如果ShoppingPortalClient直接继承VendorAdaptee,该怎么办?
  • In which scenario we need adapter class? 在哪种情况下我们需要适配器类?
  • why instead of simple inheritance a needed class, creating this pattern to access another class method? 为什么不是简单的继承需要的类,创建这个模式来访问另一个类方法?

Sometimes you have a given API that you can't change (legacy/external-library/etc...) and you want to make your classes be able to work with that API without changing their code. 有时您有一个无法更改的给定API(遗留/外部库/等等),并且您希望使您的classes能够使用该API而无需更改其代码。

Lets say you use an API which has an ISomethingToSerialize 假设您使用的是具有ISomethingToSerialize的API

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

That API also has a Serialize function: 该API还具有Serialize功能:

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

Now you have a class in your code, and you don't want or not able to change it, let's call it MyUnchangeableClass . 现在你的代码中有一个class ,你不想或不能改变它,我们称之为MyUnchangeableClass

This class doesn't implement ISomethingToSerialize but you want to serialize it using the API so you create AdapterClass which implement ISomethingToSerialize to allow MyUnchangeableClass to use it without implementing it by itself: 这个class没有实现ISomethingToSerialize但你要使用序列化它API ,所以你创建AdapterClass它们实现ISomethingToSerialize允许MyUnchangeableClass使用它本身不执行它:

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

    MyUnchangeableClass mInstance;

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

Now you can use 现在你可以使用了

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

to serialize an instance of MyUnchangeableClass even though it doesn't meet the requirements of the API by itself. 序列化MyUnchangeableClass一个实例,即使它本身不符合API的要求。

You've got the idea totally wrong. 你的想法完全错了。 The VendorAdaptee is the instance of code that produce data, where the ShoppingPortalClient is the one who wants to consume it. VendorAdaptee是生成数据的代码实例,其中ShoppingPortalClient是想要使用它的人。

Let me explain what would be the real world situation. 让我解释一下现实世界的情况。 You are implementing the shop, and someone else has been implemented a service to give you data about their products(VendorAdaptee). 您正在实施该商店,并且其他人已实施服务以向您提供有关其产品的数据(VendorAdaptee)。 The simple way of doing it is to simply call their methods and use the data, right? 这样做的简单方法是简单地调用他们的方法并使用数据,对吧? But it is their service and they might want to change it later while you don't want to upload your whole solution and release a new version. 但这是他们的服务,他们可能希望稍后更改它,而您不想上传整个解决方案并发布新版本。 Therefore, you need an adapter in between to make sure that the data will be send to your real code with the format that you need, and you simply don't care about the address, method name or data format that has been supported by your vendor. 因此,您需要一个适配器,以确保数据将以您需要的格式发送到您的实际代码,而您根本不关心您支持的地址,方法名称或数据格式供应商。


about your questions: 关于你的问题:

Inheritance is not in any way the case. 遗传绝不是这种情况。 Conceptually speaking, a shop is not a vendor in any way. 从概念上讲,商店不是任何供应商。 considering the code, you have nothing similar in any of those 2, and the behavior is totally different. 考虑到代码,你在这两个代码中没有任何相似之处,并且行为完全不同。 one is providing data while the other use it. 一个是提供数据而另一个是使用它。

The main reason you would use an adapter is for legacy code that you don't want to mess with - or a third party that you won't to fit into a certain interface. 您使用适配器的主要原因是您不想搞砸的遗留代码 - 或者您不适合某个界面的第三方。

There are other reasons, usually depending on how you find easier to develop and if using the adapter design pattern makes sense to you. 还有其他原因,通常取决于您如何发现更容易开发以及使用适配器设计模式对您有意义。 I don't see it as very useful in other cases though. 但我认为它在其他情况下并不十分有用。

First of all I also don't think this is a good example for Adapter pattern. 首先,我也不认为这是适配器模式的一个很好的例子。 Adapter pattern is much meaningful when you can't directly use one particular kind of class(say A) in your class(say B), instead you implement another class(say C) which can be directly used inside your class (B) and it(C) can directly use the first one(A). 当你不能在你的类中直接使用一种特定类(比如说A)时,适配器模式是很有意义的(比如说B),而是你实现了另一个类(比如说C),它可以在你的类中直接使用(B)和它(C)可以直接使用第一个(A)。

You might ask what will be the examples where B cannot directly use A. There's few. 你可能会问B不能直接使用A的例子。很少。

  • A's methods don't return the type which is ideally needed by B. A的方法不返回B理想需要的类型。
  • So we don't to mess up with adding the conversion need by B inside B. Instead we give responsibility to C to do it for B. 因此,我们不要在B内部添加B的转换需求。相反,我们负责C为B执行此操作。
  • It might not look natural for B to contain A. etc. B含有A等可能看起来不自然。

Back to your questions 回到你的问题

(1) It is meaningful if you ask, (1)如果你问,这是有意义的,

What, if ShoppingPortalClient directly 'uses' VendorAdaptee? 什么,如果ShoppingPortalClient直接'使用' VendorAdaptee?

Just because it is the main class, it has been used as a demo, not to show the structure. 仅仅因为它是主类,它已被用作演示,而不是显示结构。 And one thing to add, just because you want to call another class's method, don't inherit it unless it is meaningful. 还有一件事要补充,只是因为你想要调用另一个类的方法,除非它有意义,否则不要继承它。 In this scenario composition is preferred. 在这种情况下,优选组合物。 For the question why not 'using', just assume it cannot. 对于为什么不“使用”的问题,假设它不能。 But you rather ask why cannot. 但你宁愿问为什么不能。 The answer I can give in this example is just assume it is not natural to call Adaptee. 我在这个例子中给出的答案就是假设调用Adaptee是不自然的。 That's why I said it is not a good example. 这就是为什么我说这不是一个好例子。 :) :)

(2), (3) I think you can get the answer from the description I have provided so far. (2),(3)我认为你可以从我迄今提供的描述中得到答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM