Шаблон адаптера против замены Лисков

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

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

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

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

Рисунок 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 (классовая версия шаблона адаптера)
  2. Создавая экземпляр TextView внутри объекта TextShape и реализуя интерфейс TextShape с помощью экземпляра TextView (объектная версия шаблона адаптера).

Адаптер класса

Рисунок 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 действительным отношением «является»? А если нет, то не нарушает ли это принцип подстановки Лисков?


person Nilesh    schedule 25.02.2011    source источник
comment
Я думаю, что это не нарушает строго LSP, но почему бы не использовать способ компоновки? Он более развязан.   -  person Matej Baćo    schedule 25.02.2011


Ответы (1)


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

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

Я бы вообще предпочел способ делегата.

person Don Roby    schedule 25.02.2011