2014-04-02 163 views
0

我正在学习适配器模式,并使用以下链接查看代码。我的代码和示例代码的区别在于,我删除了ITarget接口,并直接在Client中创建对象。实现适配器模式的困惑

我知道使用接口的重要性,但是否真的有必要使用的界面,更具体地说,是没有创建界面,我是违反适配器模式规则

Adapter Pattern Example

我的代码(不包括接口)

class Program 
    { 
     static void Main(string[] args) 
     { 
      Adapter obj = new Adapter(); 
      Client client = new Client(obj); 

      client.MakeRequest(); 
     } 
    } 

    public class Client 
    { 
     private Adapter _target; 

     public Client(Adapter target) 
     { 
      _target = target; 
     } 

     public void MakeRequest() 
     { 
      _target.MethodA(); 
     } 
    } 


    public class Adaptee 
    { 
     public void MethodB() 
     { 
      Console.WriteLine("MethodB called"); 
     } 
    } 


    public class Adapter 
    { 
     Adaptee _adaptee = new Adaptee(); 

     public void MethodA() 
     { 
      _adaptee.MethodB(); 
     } 
    } 

感谢。

回答

2

适配器的重点在于适配器可以用于需要某种类型的地方,而不是适配器的类型。假设你有一个方法MyMethod(MyParameterType m)。此方法需要MyParameterType类型的参数。但是你没有这种类型的对象。相反,您有一个具有类似功能的对象(可能来自第三方库)。但是,此对象不是MyParameterType类型,而是MyOtherType类型。当然,你不能直接将对象传递给方法。这就是适配器的作用。

你需要一个对象传递给方法。因此,这个对象的类型是MyParameterType;它可能是一个接口或类。所以Adapter必须实现或继承这种类型。否则,这是没有意义的。您只需要具有与MyOtherType类型的对象相同功能的另一个类,但不能在任何地方使用它。

总结,适配器用于弥补架构不匹配。当你有几个需要一起玩但不应该这样做的库时,通常会发生这种情况。如果您只有自己开发的代码,那么适配器很少是必需的,因为您可以让对象实现您所需的接口。这在第三方代码中是不可能的。所以你介绍适配器。所以最终,适配器会掩盖一个对象,让客户看起来很熟悉,即使它不是。界面是必要的,以使其熟悉。所以是的,你的代码不是一个适配器。

+0

+1。很好的解释。谢谢。 –

1

这里的问题是您已经明确地将客户端耦合到适配器,并隐含地表示该适配器的工作方式。

当你开始使用依赖注入时,接口和这个模式会得到回报。

假设我有:

public Client(IAdapter target) ... 

现在我可以改变适配器实现的行为,而客户端类正在发生任何变化:

interface IAdapter 
{ 
    void MethodA(); 
} 

interface IAdaptee 
{ 
    void MethodB(); 
} 

class Adapter<TAdaptee> : IAdapter where TAdaptee : IAdaptee, new() 
{ 
    private TAdaptee _adaptee; 

    public Adapter() 
    { 
     _adaptee = new TAdaptee(); 
    } 

    public void MethodA() 
    { 
     _adaptee.MethodB(); 
    } 
} 

class AdapteeA : IAdaptee 
{ 
    public void MethodB() 
    { 
     Console.WriteLine("AdapteeA"); 
    } 
} 

class AdapteeB : IAdaptee 
{ 
    public void MethodB() 
    { 
     Console.WriteLine("AdapteeB"); 
    } 
} 
的东西

然后,像NInject绑定up your system:

class Program 
{ 
    private static StandardKernel _kernel; 

    static void Main(string[] args) 
    { 
     _kernel = new StandardKernel(); 

     _kernel.Bind<IAdapter>().To<Adapter<AdapteeA>>(); 

     var adapter = _kernel.Get<IAdapter>(); 

     adapter.MethodA(); 
    } 
} 

您可以更改您的适配器和您的适配器,而无需客户知道其差异。即客户是从两者解耦

再次指出这点我可以换到AdapteeB

_kernel.Bind<IAdapter>().To<Adapter<AdapteeB>>(); 

它走的更远也有类似的事情禁忌变化,但这超出了范围。

+0

+1。很好的解释。 –