سؤال

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.

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). This method expects a parameter of type 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. 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; may it be an interface or class. So the Adapter has to implement or inherit this type. 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.

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.

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:

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:

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. i.e. Client is decoupled from both.

Again to make this point I can change to 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 مع الإسناد
لا تنتمي إلى StackOverflow
scroll top