Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adapter Pattern vs Liskov Substitution

The Adapter design pattern is used to convert the interface of a class (Target) into another interface (Adaptee) clients expect. Adapter lets incompatible classes work together that could not otherwise because of their incompatible interfaces.

The Adapter Pattern can be implemented in two ways, by Inheritance (class version of Adapter pattern) and by Composition (object version of Adapter pattern).

My question is about the class version of adapter pattern which is implemented using Inheritance.

Here is an example of Drawing Editor:

Figure 1:

interface Shape   
{   
        Rectangle BoundingBox();   

        Manipulator CreateManipulator();   
}   

class TextView   
{   
        public TextView() { }   

        public Point GetOrigin() { }   

        public int GetWidth() { }   

        public int GetHeight() { }   
}  
interface Shape
{
        Rectangle BoundingBox();

        Manipulator CreateManipulator();
}

class TextView
{
        public TextView() { }

        public Point GetOrigin() { }

        public int GetWidth() { }

        public int GetHeight() { }
}

We would like to reuse TextView class to implement TextShape, but the interfaces are different, and therefore, TextView and Shape objects cannot be used interchangeably.

Should one change the TextView class to conform to the shape interface? Perhaps not.

TextShape can adapt the TextView interface to the shape's interface, in one of the two ways:

  1. By inheriting Shape's interface and TextView's implementation (class version of Adapter patter)
  2. By composing a TextView instance inside the TextShape object and implementing the TextShape's interface by using the TextView instance (object version of Adapter pattern).

Class Adapter

Figure 2:

interface Shape   
{   
    Rectangle BoundingBox();   

    Manipulator CreateManipulator();   
}   

class TextView   
{   
    public TextView() { }   

    public Point GetOrigin() { }   

    public int GetWidth() { }   

    public int GetHeight() { }   
}   

class TextShape : TextView, Shape   
{   
    public Rectangle BoundingBox()   
    {   
        Rectangle rectangle;   
        int x, y;   
        Point p = GetOrigin();   
        x = GetWidth();   
        y = GetHeight();   

        //...   

        return rectangle;   
    }  

    #region Shape Members   

    public Rectangle Shape.BoundingBox()   
    {   
        return new TextBoundingBox();   
    }   

    public Manipulator Shape.CreateManipulator()   
    {   
        return new TextManipulator();   
    }  

    #endregion   
}  

Now for the question :-). Is TextShape inheriting from Shape and particularly from TextView a valid "is a" relationship? And if not, doesn't it violate Liskov's Substitution Principle?

like image 950
Nilesh Avatar asked Feb 25 '11 15:02

Nilesh


People also ask

Is there a difference between Adaptor and facade pattern?

The Adapter pattern allows the interface of an existing class to be used as another interface. The Façade pattern enables an object to provide a simplified interface to a larger body of code, such as a class library.

What is the difference between Bridge pattern and Adapter pattern?

A Bridge pattern can only be implemented before the application is designed. Allows an abstraction and implementation to change independently whereas an Adapter pattern makes it possible for incompatible classes to work together.

When should an Adapter pattern be used?

we use an adapter that converts one to other. This example is pretty analogous to Object Oriented Adapters. In design, adapters are used when we have a class (Client) expecting some type of object and we have an object (Adaptee) offering the same features but exposing a different interface.

What is the difference between adapter and decorator pattern?

Main difference is:Decorator is used to decorate individual objects at run-time. Adapter is used to add features to the class and therefore to ALL of its objects. It's true that Adapter targets the class and therefore to ALL of its objects.


1 Answers

It doesn't violate the Liskov Substitution Principle unless you have something in the subclass that makes it behave in a way that doesn't make sense for the superclass (violating the contract of the superclass). This is incomplete code of course, but I don't see any sign of that.

It might violate the Single Responsibility Principle, but I'm not sure that's a giant concern in an adapter implementation.

I'd generally prefer the delegate way.

like image 88
Don Roby Avatar answered Sep 17 '22 12:09

Don Roby