简体   繁体   English

实施适配器模式时的困惑

[英]Confusion in implementing adapter pattern

I am learning Adapter pattern, and used following link to see code. 我正在学习适配器模式,并使用以下链接查看代码。 Difference in my code and example code is, I removed ITarget interface, and directly created object in Client. 我的代码和示例代码的区别在于,我删除了ITarget接口,并在Client中直接创建了对象。

I know importance of using Interface, but is it really necessary to use interface, more specifically, by not creating interface, am I violating Adapter Pattern rule ? 我知道使用接口的重要性,但是确实需要使用接口,更具体地说,通过不创建接口来违反 接口模式规则吗?

Adapter Pattern Example 适配器模式示例

My Code (without interface) 我的代码(无界面)

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

Thanks. 谢谢。

The whole point of an adapter is that the adaptee can be used wherever a certain type is needed which is not the adaptee's type. 适配器的全部目的是,可以在需要某种特定类型(而不是适配器类型)的地方使用适配器。

Assume that you have a method MyMethod(MyParameterType m) . 假设您有一个方法MyMethod(MyParameterType m) This method expects a parameter of type MyParameterType . 该方法需要一个类型为MyParameterType的参数。 But you don't have an object of this type. 但是您没有这种类型的对象。 Instead you have an object that has similar functionality (maybe from a third-party library). 相反,您有一个具有类似功能的对象(可能来自第三方库)。 However, this object is not of type MyParameterType , but of type MyOtherType . 但是,此对象不是MyParameterType类型,而是MyOtherType类型。 Of course, you can't directly pass the object to the method. 当然,您不能直接将对象传递给方法。 That's where the adapter comes into play. 这就是适配器起作用的地方。

You need an object to pass to the method. 您需要一个对象来传递给方法。 Hence, it is essential that this object is of type MyParameterType ; 因此,此对象的类型MyParameterTypeMyParameterType may it be an interface or class. 可能是接口或类。 So the Adapter has to implement or inherit this type. 因此, Adapter必须实现或继承此类型。 Otherwise, it does not make sense. 否则,这是没有意义的。 You would just have another class with the same functionality as the object of type MyOtherType , but you can't use it anywhere. 您将拥有另一个具有与MyOtherType类型的对象相同功能的类,但是您无法在任何地方使用它。

Summarizing, the adapter is used to bridge architectural mismatch. 总而言之,适配器用于弥合体系结构不匹配。 This often occurs when you have several libraries that need to play together but were not supposed to do so. 当您有多个需要一起播放但不应该一起播放的库时,通常会发生这种情况。 If you have only code that has been developed by yourself, adapters are rarely necessary because you can let the objects just implement the interface you need. 如果只有您自己开发的代码,则几乎不需要适配器,因为可以让对象仅实现所需的接口。 This is not possible in third-party code. 这在第三方代码中是不可能的。 So you introduce adapters for that. 因此,您为此引入了适配器。 So in the end, the adapter disguises an object to look familiar to a client, even if it is not. 因此,最后,适配器伪装了一个对象,使客户端看起来很熟悉,即使它不是。 The interface is necessary to make it familiar. 该界面对于使其熟悉是必不可少的。 So yes, your code is not an adapter. 是的,您的代码不是适配器。

The problem here is you've explicitly coupled Client to the Adapter and implicitly to the behavior of how that adapter works. 这里的问题是您已将Client显式地耦合到适配器,并且隐式地耦合到该适配器如何工作的行为。

Interfaces and this pattern pay off when you start using dependency injection. 当您开始使用依赖项注入时,接口和此模式将奏效。

Assume I have: 假设我有:

public Client(IAdapter target) ...

Now I can change the behavior of the adapter implementation without the Client class being changed at all: 现在, 我可以更改适配器实现的行为,而无需完全更改 Client类:

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

Then with something like NInject you bind up your system: 然后使用NInject之类的东西绑定您的系统:

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

You can change your adapter and your adaptee, without client ever knowing the difference. 您可以更改适配器和适配器,而无需客户知道其区别。 ie Client is decoupled from both. 即客户端从两者分离

Again to make this point I can change to AdapteeB : 再次说明这一点,我可以更改为AdapteeB

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

It does go further too, with things like contra-variance, but that is beyond scope. 它确实在进一步发展,例如逆方差,但这超出了范围。

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

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