实现适配器模式时的混乱



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

我知道使用接口

的重要性,但是真的有必要使用接口吗,更具体地说,通过不创建接口,我是否违反了适配器模式规则

适配器模式示例

我的代码(无接口)

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

谢谢。

适配器的全部意义在于,适配器可以在需要某种类型而不是适配器类型的地方使用。

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

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

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

这里的问题是您已将客户端显式耦合到适配器,并隐式耦合到该适配器的工作方式。

接口和此模式在开始使用依赖关系注入时会得到回报。

假设我有:

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

它确实也走得更远,比如逆方差,但这超出了范围。

最新更新