Design Patterns ----- Разомкнуто Принцип

Открытый Закрытый Принцип

В объектно-ориентированного проектирования имеет много популярных идей, таких как «все переменные-члены должны быть установлены на частные (Private)», «чтобы избежать использования глобальных переменных (глобальные переменные)», «с помощью идентификации типа во время выполнения (RTTI: Run Time Type Identification, например, dynamic_cast) опасно «и так далее. Итак, что же является источником этих идей? Почему они делают это определено? Эти идеи всегда правильно? В данной статье описываются основы этих идей: Open Closed принцип (Open Closed Принцип).

Ивар Якобсон однажды сказал: «Все системы различаются в его жизненном цикле, до тех пор, пока система является разработкой версии выше нее нужно будет иметь в виде.».

Все системы изменяются в течение их жизненного цикла. Это следует иметь в виду при разработке систем, как ожидается, продлится дольше, чем первая версия.

Таким образом, в конце концов, как мы можем построить конструкцию устойчивую к лицу этих изменений, так что программное обеспечение жизненного цикла длится дольше делать?

Уже в 1988 году Бертран Мейер дает указания по предложению, он создал очень известный современный открытый замкнутый принцип. Применить его точные слова: «Программные объекты (классы, модули, функции и т.д.), чтобы иметь дело с увеличенным открытым, но закрыты для модификации.».

Программное обеспечение лиц (классы, модули, функции и т.д.) должны быть открыты для расширения, но закрыты для модификации.

Когда программа нуждается изменения приводят к более зависимым каскадным модулям претерпели изменения, то программа покажет особенности того, что мы называем «плохой дизайн (плохой дизайн)» есть. Применение соответственно становится ломким, жестким, непредсказуемо и не может быть использовано повторно. Открытый Закрытый Принцип (Открытый Закрытый принцип), что решить эти проблемы, возникающие, следует подчеркнуть, что вы никогда не должны изменить конструкцию модуля. При изменении требований, вы можете продлить этот модуль поведения путем добавления нового кода, вместо того, чтобы изменить код, который уже существует может работать.

Открытый Закрытый Принцип (Разомкнуто Принцип) Описание

Модуль совместим с Open Closed Принцип имеет две основные функции:

1. Они "открыты для расширения (Open For Extension)".

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

2. Они «закрыты для модификаций (Закрыто для модификации)».

Модуль исходный код не может быть нарушена, и ни один не было разрешено модифицировать исходный код.

Появляется над двумя характеристиками противоречивы, так как правило, обычным способом, чтобы модифицировать поведение модуля расширения модуля. Модуль не может быть изменен, как правило, считается, что фиксированное поведение. Так как эти два противоположных свойства сосуществуют это?

Абстракция является ключевым.

Абстракция является ключом.

При использовании объектно-ориентированных методов проектирования, вы можете создать фиксированный набор абстрактных и можете проводить неограниченное сообщество выразить. Абстрактные здесь, относится к абстрактному базовому классу, бесконечное число кругов могут вести себя по подклассу производного может быть представлена. Модуль для абстрактного класса вмешательства возможно, и этот модуль может быть закрыт для модификации, поскольку она опирается на фиксированную абстракции. Тогда поведение модуля может быть расширен за счет создания абстрактных производных классов.

Пример: ссылки Client / Server

На рисунке 1 показана простая конструкция не соответствует принципам открытой закрытой.

(Фиг.1:. Замкнутый клиент)

Клиентские и серверные классы определенные категории (класс бетона), мы не можем гарантировать, что функция члена сервер является виртуальным. Здесь класс Клиент использует класс Server. Если мы хотим использовать другой объект Client Object Server, необходимо изменить класс для использования новых классов Client Server и объектов.

На рисунке 2 показана соответствующая конструкция в соответствии с принципом открытия до закрытой.

(Фиг. 2: Open Client)

В этом примере, AbstractServer класс является абстрактным классом, и включает в себя чистую виртуальную функцию-член. Класс клиента опирается на абстрактные, но использовать объект класса экземпляра клиента сервера производного класса. Если нужно использовать другой класс целевого клиента сервера, класс может быть получен из AbstractServer новый подкласс класса Client остается неизменным.

Пример: форма аннотация

Рассмотрим следующий пример. У нас есть приложение должно нарисовать круг (круг) и квадрат (площадь) на стандартном окне GUI. Круглые и квадратные должны быть сделаны в определенном порядке. Круглые и квадратные будет создан в том же списке, и для поддержания надлежащей последовательности, и программа должна быть в состоянии пройти список в порядке и сделать все круглые и квадратные.

В языке C, использование технологии не в состоянии удовлетворить открытый закрытый принцип. Мы могли бы решить эту проблему путем следующих кодовых шоу.

enum ShapeType {circle, square};

struct Shape 
{
    ShapeType itsType;
};

struct Square 
{
    ShapeType itsType;
    double itsSide; 
    Point itsTopLeft;
};

struct Circle 
{
    ShapeType itsType;
    double itsRadius; 
    Point itsCenter;
};

void DrawSquare(struct Square*);
void DrawCircle(struct Circle*);
typedef struct Shape *ShapePointer;

void DrawAllShapes(ShapePointer list[], int n)
{
    int i;
    for (i=0; i<n; i++)
    {
        struct Shape* s = list[i];
        switch (s->itsType)
        {
            case square:
                DrawSquare((struct Square*)s);
                break;
            case circle:
                DrawCircle((struct Circle*)s);
                break;
        }
    }
}

Здесь мы видим, определение набора структур данных, эти структуры являются такими же, за исключением того, что первый элемент, другой отличается. Эта структура идентифицируется типа кодом первого элемента представлена ​​окружностью (окружность) или квадрат (площадь). DrawAllShapes структуры обход массива указателя на функцию, а затем проверить код типа, который соответствует вызову функции (или DrawCircle DrawSquare).

Здесь функция DrawAllShapes не соответствует принципу открытости закрыты, потому что это не гарантированно остаются закрытыми для новых видов Shape. Если мы хотим расширить эту функцию, так что она может поддерживать графический список и содержит треугольник (треугольник) определен, то мы должны изменить эту функцию. В самом деле, всякий раз, когда нам нужно нарисовать новый тип фигуры, мы должны изменить эту функцию.

Конечно, эта программа только один пример. На практике DrawAllShapes функционируют заявления переключателя будет продолжаться в применении различных интер-функции продолжает звонить, и каждая функция просто немного по-другому. Увеличение таких приложений подразумевает необходимость в новой форме поиска помещает все подобное заявление переключателя (или, если / иначе цепь) существует, а затем добавить новые функции Shape. Кроме того, чтобы сделать все переключатель заявления (или, если / иначе цепь) имеет аналогичные функции DrawAllShapes такую ​​хорошую структуру также маловероятно. Скорее всего, и если утверждение является числом логических операторов, чтобы связать друг с другом, или в виде стека пункта саза переключателя. Таким образом, чтобы найти и понять эти вопросы во всех позициях, а затем добавить новое графическое определение не является простым делом.

Следующий код показано решение Cicle / Площадь вопроса в соответствии с принципом открытой закрытой.

public abstract class Shape
{
    public abstract void Draw();
}

public class Circle : Shape
{
    public override void Draw()
    {
      // draw circle on GUI
    }
}

public class Square : Shape
{
    public override void Draw()
    {
      // draw square on GUI
    }
}

public class Client
{
    public void DrawAllShapes(List<Shape> shapes)
    {
      foreach (var shape in shapes)
      {
        shape.Draw();
      }
    }
}

В этом примере мы создаем форму абстрактный класс, абстрактный класс содержит чисто виртуальную функцию Draw. И это происходит от и Square Circle класса Shape.

Здесь следует отметить, что, если мы хотим, чтобы расширить поведение DrawAllShapes функционировать, чтобы нарисовать новый тип графика, что нам нужно сделать, это добавить подкласс, производный от класса Shape. В DrawAllShapes функции вы не должны быть изменены. Поэтому DrawAllShapes в соответствии с принципом открытия до закрытого, его поведение может быть изменено и расширено его не до конца.

В более реалистичном случае, класс Shape может содержать ряд методов. Но добавить новое графическое приложение по-прежнему очень просто, потому что только нужно сделать, это создать производный класс для реализации этих функций. В то же время, мы больше не нужно, чтобы найти все, что вам нужно изменить местоположение в приложении.

Поскольку изменения в программе в соответствии с открытым принципу закрытой является то, что при добавлении нового кода, а не модификации существующего кода, вид каскадных изменений описывалось ранее не существовало бы.

Стратегическое закрытие (стратегическое закрытие)

Для того, чтобы разобраться в программе не 100% полный закрыт. Например, представьте себе формы в приведенном выше примере, если мы решим, круг должен быть в первую очередь отбирались до площади, функцию DrawAllShapes, что будет тогда? Функция DrawAllShapes не возможно такое изменение, чтобы держать закрытыми. Как правило, не говоря, независимо от того, насколько близко конструкция модуля, всегда есть большое разнообразие изменений, чтобы разорвать этот замкнутый.

Поэтому нереально полностью закрыт, то необходимо обратить внимание на стратегию. Другими словами, программисты должны разработать свой замкнутый скрининг , какие изменения . Это требует прогнозирования на основе опыта. Опытные дизайнеры сделали бы хорошо , чтобы понять , где пользователи и промышленности для определения вероятности различных изменений. Вы можете определить , остается открытым закрытым принцип, скорее всего, изменится.

Абстрактный дисплей закрыт, чтобы получить

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

Стратегия секвенирование, учитывая любые два объекта могут быть найдены, которые должны быть сделаны в первую очередь. Таким образом, мы можем определить метод, названный Precedes формы, он может принимать другую форму в качестве параметра и возвращает результат типа BOOL. Если результат верен это означает, что вызов должен быть получен объект Shape перед Shape объекта в качестве параметра.

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

Ниже показан код, который прост в реализации.

public abstract class Shape
{
    public abstract void Draw();

    public bool Precedes(Shape another)
    {
      if (another is Circle)
        return true;
      else
        return false;
    }
}

public class Circle : Shape
{
    public override void Draw()
    {
      // draw circle on GUI
    }
}

public class Square : Shape
{
    public override void Draw()
    {
      // draw square on GUI
    }
}

public class ShapeComparer : IComparer<Shape>
{
    public int Compare(Shape x, Shape y)
    {
      return x.Precedes(y) ? 1 : 0;
    }
}

public class Client
{
    public void DrawAllShapes(List<Shape> shapes)
    {
      SortedSet<Shape> orderedList =
        new SortedSet<Shape>(shapes, new ShapeComparer());

      foreach (var shape in orderedList)
      {
        shape.Draw();
      }
    }
}

Этот объект был достигнут Форма сортировки объектов, и могут быть отсортированы в правильном порядке. Но мы до сих пор не имеют надлежащего рода абстракции. В этом данном случае, индивидуум должен был бы переопределить метод объекта Precedes формы, чтобы задать порядок. Как это будет работать? Что нам нужно написать код, чтобы обеспечить предшествующий круг площади до того, как можно сделать?

public bool Precedes(Shape another)
{
    if (another is Circle)
        return true;
    else
        return false;
}

Как можно видеть, эта функция не соответствует открытому закрытому принципу. Невозможно держать его закрытым в новой форме подкласса производного. Каждый раз, когда создается новый Shape-производный класс, этот метод всегда будет изменен.

Использование «драйвера данных (Data Driven)» метод достижения закрытого

Привод стола (таблица Driven) метод может достичь закрытия класса Shape производного, не заставляя изменять каждый производный класс.

Ниже показан возможный дизайн.

private Dictionary<Type, int> _typeOrderTable = new Dictionary<Type, int>();

private void Initialize()
{
    _typeOrderTable.Add(typeof(Circle), 2);
    _typeOrderTable.Add(typeof(Square), 1);
}

public bool Precedes(Shape another)
{
    return _typeOrderTable[this.GetType()] > _typeOrderTable[another.GetType()];
}

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

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

Дальнейшее расширение закрыто

Это не конец истории.

Мы можем контролировать иерархию Shape и DrawAllShapes функции закрытия для сортировки различных типов Shape основы. Тем не менее, форма производных классов без определения типа модели сопоставления незамкнутого. Может показаться, мы надеемся рода Shape, основанный на структуре более высокого уровня. Полное исследование этого вопроса выходит за рамки данной статьи, но заинтересованные читатели могут подумать, как реализовать. Такие, как позволяет класс для хранения OrderedShape OrderedObject абстрактного класса, и реализовать свой собственный наследовать от Shape и класс OrderedObject.

резюме

О открытом закрытом принципе (Разомкнуто принцип), есть много можно говорить. Во многих отношениях этот принцип является основой объектно-ориентированного проектирования. Всегда следовать принципу, чтобы продолжать получать максимальную выгоду от объектно-ориентированной технологии, например: повторное использование и ремонтопригодность. В то же время, принцип не сопровождается использованием объектно-ориентированного языка программирования, который может быть достигнут. Скорее всего, это требует, чтобы программисты больше сосредоточиться на применении технологии абстрагировать часть этих программ, как правило, к изменению.

справочный материал

рекомендация

отwww.cnblogs.com/MessiXiaoMo3334/p/11808533.html