Cardin
Cardin

Reputation: 5487

Use of Adapter/Facade pattern to anticipate incompatible interfaces and complexity?

Adapter pattern is mentioned in Wikipedia to fix incompatibilities between an expected interface and an actual interface.

Facade pattern is said to obscure complex implementations and present a simplified API.

However, would these patterns be used even in the absence of these issues? Aka, to use these patterns prematurely in anticipation of future incompatibility and complexity?

I have encountered code where a wrapper class was implemented with an exact copy of the interface of the inner class - it had all the public methods of the original with the exact same parameters. The wrapper class and the inner class were also defined in the same assembly.

Like so:

public class ClassifierImplementation
{
    private Classifier classifier_;
    public Wrapper() { classifier_ = new Classifier(); }

    public int[] Classify(double[] values, int seed)
    {
        return classifier_.Classify(values, seed);
    }

    // And other more public methods
}

What would be the rationale behind such an implementation?

Upvotes: 0

Views: 217

Answers (2)

NightOwl888
NightOwl888

Reputation: 56869

I have encountered code where a wrapper class was implemented with an exact copy of the interface of the inner class - it had all the public methods of the original with the exact same parameters. The wrapper class and the inner class were also defined in the same assembly.

What would be the rationale behind such an implementation?

One reason is to create an abstraction that the wrapper class can implement.

An example of this is the HttpContext class in ASP.NET. The original ASP.NET implementation was a class called HttpContext, which had a very large and complicated interface.

When unit testing came into the scene, it was quickly discovered that creating an instance of this class just for a unit test was not very practical, since the class itself has several dependencies and read-only properties that cannot be set.

So, in a later version of .NET, the HttpContextBase abstract class was created with exactly the same interface as HttpContext. Also, it shipped with a concrete implementation called HttpContextWrapper, which took the HttpContext instance as a constructor parameter.

Now, testing is much easier because the code under test need only take a dependency on HttpContextBase. It is easy to use a mocking library to define just a few properties at a time in order to satisfy the logic of the code under test.

The live application will generally have HttpContextWrapper injected into it instead, and since it has the exact same interface as HttpContext it does exactly the same thing as the non-mockable HttpContext class in production.

Having the same interface means that to make existing code testable, one only need change the variable or parameter reference from HttpContext to HttpContextBase and none of the other code needs to change.

Upvotes: 1

Dhruv Rai Puri
Dhruv Rai Puri

Reputation: 1375

I will go with the analysis 1 pattern at a time -

  • Adapter Pattern The Classifier example given above looks like an adapter as it adapts(going by the classic definition of an object adapter) from a ClassifierImplementation to Classifier - but its not really adapting from one type to another as you mentioned that methods are same. Hence, if everything is same - why adapt!!

  • Facade Pattern - Its not a facade as facade is made to simplify the interface(methods in this case) whereas in this case the methods/method definitions are same for ClassifierImplementation and Classifier. ClassifierImplementation seems to be more of a wrapper(as you also mentioned) over Classifier which brings me to my next point -

  • Proxy Pattern - It looks like an instance of Proxy pattern where ClassifierImplementation is trying to control access to an instance of Classifier which it is holding. This way Classifier implementation can modify the incoming request params or outgoing return values as per its needs, and the method definitions do not change.

Lastly, all said and done, ClassifierImplementation class should be renamed to something more meaningful (like ClassifierProxy) as it is not extending or implementing anything. The current name creates confusion and reduces readability.

Note - ClassifierImplementation can implement the same interface which Classifier is implementing but then it would be more of a decorator than proxy.

Upvotes: 1

Related Questions