Адаптер Pattern против замены Liskov - PullRequest
9 голосов
/ 25 февраля 2011

Шаблон проектирования адаптера используется для преобразования интерфейса класса (Target) в другой интерфейс (Adaptee), ожидаемый клиентами. Adapter позволяет несовместимым классам работать вместе, что иначе невозможно из-за их несовместимых интерфейсов.

Шаблон адаптера может быть реализован двумя способами: Наследование (версия класса шаблона адаптера) и Композиция (объектная версия шаблона адаптера).

Мой вопрос касается классовой версии шаблона адаптера, которая реализована с использованием Inheritance.

Вот пример редактора чертежей:

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

Мы хотели бы повторно использовать класс TextView для реализации TextShape, но интерфейсы отличаются, и поэтому объекты TextView и Shape нельзя использовать взаимозаменяемо.

Следует ли изменить класс TextView, чтобы он соответствовал интерфейсу формы? Возможно, нет.

TextShape может адаптировать интерфейс TextView к интерфейсу фигуры одним из двух способов:

  1. Унаследовав интерфейс Shape и реализацию TextView (классовая версия Adapter patter)
  2. Путем создания экземпляра TextView внутри объекта TextShape и реализации интерфейса TextShape с использованием экземпляра TextView (объектная версия шаблона 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   
}  

Теперь к вопросу :-). Является ли TextShape, наследуемое от Shape и, в частности, от TextView, допустимым отношением "is"? А если нет, то не нарушает ли принцип подстановки Лискова ?

1 Ответ

5 голосов
/ 26 февраля 2011

Это не нарушает принцип подстановки Лискова, если только у вас нет чего-то в подклассе, которое заставляет его вести себя таким образом, который не имеет смысла для суперкласса (нарушая контракт суперкласса). Конечно, это неполный код, но я не вижу никаких признаков этого.

Это может нарушить Принцип единой ответственности , но я не уверен, что это серьезная проблема в реализации адаптера.

Я бы предпочел делегировать путь.

...