实现适配器模式的困惑

时间:2014-04-02 07:53:23

标签: c# .net design-patterns adapter

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

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

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 个答案:

答案 0 :(得分:2)

适配器的重点在于,可以在需要某种类型的地方使用适配器,而不是适配器的类型。

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

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

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

答案 1 :(得分:1)

此处的问题是您已将客户端显式耦合到适配器,并隐式地了解该适配器的工作方式。

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

假设我有:

public Client(IAdapter target) ...

现在我可以更改适配器实现的行为,而根本不更改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");
    }
}

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

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

再说一遍,我可以改为AdapteeB

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

它确实更进一步,具有反方差等因素,但这超出了范围。

相关问题