dir.by  
  Поиск  
Программирование, разработка, тестирование
Паттерны, шаблоны проектирования | принципы ООП | рефакторинг кода
Open/Closed Principle (Принцип открытости/закрытости) SOLID проектирование
  Посмотрели 5327 раз(а)    
 Open/Closed Principle (Принцип открытости/закрытости) SOLID проектирование 
последнее обновление: 19 октября 2018
Программные сущности … должны быть открыты для расширения, но закрыты для модификаци.

Суть этого принципа состоит в том, что система должна быть построена таким образом, что все ее последующие изменения должны быть реализованы с помощью добавления нового кода, а не изменения уже существующего.

Наш модуль должен быть разработан так, чтобы новая функциональность могла быть добавлена только при создании новых требований.
«Закрыт для модификации» означает, что мы уже разработали класс, и он прошел модульное тестирование. Мы не должны менять его, пока не найдем ошибки.
Как говорится, класс должен быть открытым только для расширений и в C# мы можем использовать для этого наследование.
Рассмотрим пример "Сохранение книги в файл"
  C#     Создаем новое C# консольное приложение... и напишем код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO; // подключаем библиотеку для работы с файлами

namespace ConsoleApplication1
{
     enum FileFormat
     {
          TXT = 1,
          HTML = 2,
     }

     // класс Book
     class Book
     {
          // информация о книге
          public string BookName { get; set; }
          public string AuthorName { get; set; }
          public string Content { get; set; }
     }

     // класс BookFile
     class BookFile
     {
          // метод Generate сохраняет книгу в файл с нужным форматом TXT, HTML, ...
          public void Generate(Book book, FileFormat fileFormat, string filePath)
          {
               if (fileFormat == FileFormat.HTML)
               {
                    // открываем файл (стираем содержимое файла)
                    FileStream fileStream = File.Open(filePath, FileMode.Create);
                    StreamWriter output = new StreamWriter(fileStream);

                    // записываем текст
                    string text = String.Format("<HTML><b>Название</b> {0} <BR> <b>Автор</b> {1} <BR><BR> <b>Содержание</b> <BR> {2}</HTML>", book.BookName, book.AuthorName, book.Content);
                    output.Write(text);

                    // закрываем
                    output.Close();
               }
               else if (fileFormat == FileFormat.TXT)
               {
                    // открываем файл (стираем содержимое файла)
                    FileStream fileStream = File.Open(filePath, FileMode.Create);
                    StreamWriter output = new StreamWriter(fileStream);

                    // записываем текст
                    string text = String.Format("Название {0}\nАвтор {1}\nСодержание\n\n{2}", book.BookName, book.AuthorName, book.Content);
                    output.Write(text);

                    // закрываем
                    output.Close();
               }
          }
     }

     // главный класс программы
     class Program
     {
          static void Main(string[] args)
          {
               // создаем книгу
               Book myBook = new Book();

               // заполняем книгу
               myBook.BookName = "Властелин Колец";
               myBook.AuthorName = "Толкин";
               myBook.Content = "Когда-то давным давно жили эльфы... Эльфы пили молоко и кушали сыр...";

               // сохраняем книгу в текстовый файл
               BookFile bookFile1 = new BookFile();
               bookFile1.Generate(myBook, FileFormat.HTML, "d://book.html");

               // сохраняем книгу в html файл
               BookFile bookFile2 = new BookFile();
               bookFile2.Generate(myBook, FileFormat.TXT, "d://book.txt");
          }
     }
}
В примере
Если мы захотим сохранить в новый тип файла PDF, то нам понадобится добавить новое условие if в методе Generate.

  C#  
// класс BookFile
class BookFile
{
     // метод Generate сохраняет книгу в файл с нужным форматом TXT, HTML, PDF
     public void Generate(Book book, FileFormat fileFormat, string filePath)
     {
          ...
          else if (fileFormat == FileFormat.PDF)
          {
               ...
          }
     }
}


Cогласно принципу принципу открытости/закрытости наш класс должен быть:
закрыт от модификаций
открыт для расширений

Модификация метода Generate нарушает принцип открытости/закрытости.
Исправим пример BookFile, чтобы сущности были открыты для расширения
  C#  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO; // подключаем библиотеку для работы с файлами

namespace ConsoleApplication1
{
     enum FileFormat
     {
          TXT = 1,
          HTML = 2,
     }

     // класс Book
     class Book
     {
          // информация о книге
          public string BookName { get; set; }
          public string AuthorName { get; set; }
          public string Content { get; set; }
     }

     // интерфейс BookFile
     interface IBookFile
     {
          void Generate(Book book, string filePath);
     }

     // класс BookTXT реализует интерфейс IBookFile (сохранение в TXT файл)
     class BookTXT : IBookFile
     {
          public void Generate(Book book, string filePath)
          {
               // открываем файл (стираем содержимое файла)
               FileStream fileStream = File.Open(filePath, FileMode.Create);
               StreamWriter output = new StreamWriter(fileStream);

               // записываем текст
               string text = String.Format("Название {0}\nАвтор {1}\nСодержание\n\n{2}", book.BookName, book.AuthorName, book.Content);
               output.Write(text);

               // закрываем
               output.Close();
          }
     }

     // класс BookHTML реализует интерфейс IBookFile (сохранение в HTML файл)
     class BookHTML : IBookFile
     {
          public void Generate(Book book, string filePath)
          {
               // открываем файл (стираем содержимое файла)
               FileStream fileStream = File.Open(filePath, FileMode.Create);
               StreamWriter output = new StreamWriter(fileStream);

               // записываем текст
               string text = String.Format("<HTML><b>Название</b> {0} <BR> <b>Автор</b> {1} <BR><BR> <b>Содержание</b> <BR> {2}</HTML>", book.BookName, book.AuthorName, book.Content);
               output.Write(text);

               // закрываем
               output.Close();
          }
     }

     // главный класс программы
     class Program
     {
          static void Main(string[] args)
          {
               // создаем книгу
               Book myBook = new Book();

               // заполняем книгу
               myBook.BookName = "Властелин Колец";
               myBook.AuthorName = "Толкин";
               myBook.Content = "Когда-то давным давно жили эльфы... Эльфы пили молоко и кушали сыр...";

               // сохраняем книгу в текстовый файл
               IBookFile bookFile1 = new BookTXT();
               bookFile1.Generate(myBook, "d://book.txt");

               // сохраняем книгу в html файл
               IBookFile bookFile2 = new BookHTML();
               bookFile2.Generate(myBook, "d://book.html");
          }
     }
}
Добавим функциональность для сохранения книги в новый формат файла PDF
Модификаций нет
Новые добавленные строчки помечены синим цветом.
  C#  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO; // подключаем библиотеку для работы с файлами

namespace ConsoleApplication1
{
     enum FileFormat
     {
          TXT = 1,
          HTML = 2,
     }

     // класс Book
     class Book
     {
          // информация о книге
          public string BookName { get; set; }
          public string AuthorName { get; set; }
          public string Content { get; set; }
     }

     // интерфейс BookFile
     interface IBookFile
     {
          void Generate(Book book, string filePath);
     }

     // класс BookTXT реализует интерфейс IBookFile (сохранение в TXT файл)
     class BookTXT : IBookFile
     {
          public void Generate(Book book, string filePath)
          {
               // открываем файл (стираем содержимое файла)
               FileStream fileStream = File.Open(filePath, FileMode.Create);
               StreamWriter output = new StreamWriter(fileStream);

               // записываем текст
               string text = String.Format("Название {0}\nАвтор {1}\nСодержание\n\n{2}", book.BookName, book.AuthorName, book.Content);
               output.Write(text);

               // закрываем
               output.Close();
          }
     }

     // класс BookHTML реализует интерфейс IBookFile (сохранение в HTML файл)
     class BookHTML : IBookFile
     {
          public void Generate(Book book, string filePath)
          {
               // открываем файл (стираем содержимое файла)
               FileStream fileStream = File.Open(filePath, FileMode.Create);
               StreamWriter output = new StreamWriter(fileStream);

               // записываем текст
               string text = String.Format("<HTML><b>Название</b> {0} <BR> <b>Автор</b> {1} <BR><BR> <b>Содержание</b> <BR> {2}</HTML>", book.BookName, book.AuthorName, book.Content);
               output.Write(text);

               // закрываем
               output.Close();
          }
     }

     // класс BookPDF реализует интерфейс IBookFile (сохранение в PDF файл)
     class BookPDF : IBookFile
     {
          public void Generate(Book book, string filePath)
          {
               // открываем файл (стираем содержимое файла)
               FileStream fileStream = File.Open(filePath, FileMode.Create);
               StreamWriter output = new StreamWriter(fileStream);

               // записываем текст
               string text = "..." + book.Content + "..."; // pdf format
               output.Write(text);

               // закрываем
               output.Close();
          }
     }


     // главный класс программы
     class Program
     {
          static void Main(string[] args)
          {
               // создаем книгу
               Book myBook = new Book();

               // заполняем книгу
               myBook.BookName = "Властелин Колец";
               myBook.AuthorName = "Толкин";
               myBook.Content = "Когда-то давным давно жили эльфы... Эльфы пили молоко и кушали сыр...";

               // сохраняем книгу в текстовый файл
               IBookFile bookFile1 = new BookTXT();
               bookFile1.Generate(myBook, "d://book.txt");

               // сохраняем книгу в html файл
               IBookFile bookFile2 = new BookHTML();
               bookFile2.Generate(myBook, "d://book.html");

               // сохраняем книгу в pdf файл
               IBookFile bookFile3 = new BookPDF();
               bookFile3.Generate(myBook, "d://book.pdf");

          }
     }
}
Сейчас в примере:
мы добавили новый класс BookPDF и это расширение функциональности
Модификаций нет

Итог!
Наши классы соответствует Принципу открытости/закрытости
 
← Предыдущая тема
Single Responsibility Principle (Принцип единственной обязанности) SOLID проектирование
 
 
Ваши Отзывы ... комментарии ...
   
Вашe имя
Ваш комментарий (www ссылки может добавлять только залогиненный пользователь)

  Объявления  
  Объявления  
 
Введение
Что такое подкласс или дочерний класс или наследник класса? Что такое родительский класс ?
Принципы ООП
Что такое Объектно-ориентированное программирование? Принципы: абстрагирование, инкапсуляция, наследование, полиморфизм
Рефакторинг кода
Что такое рефакторинг кода ?
Шаблоны проектирования
Порождающие паттерны
Фабричный метод (Factory Method) это порождающий шаблон проектирования
Абстрактная фабрика (Abstract Factory) это порождающий шаблон проектирования
Одиночка (Singleton) это порождающий шаблон проектирования
Прототип (Prototype) это порождающий шаблон проектирования
Строитель (Builder) это порождающий шаблон проектирования

Паттерны поведения
Стратегия (Strategy) это поведенческий шаблон проектирования
S.O.L.I.D. (5 принципов проектирования программы)
Что такое SOLID ?
Single Responsibility Principle (Принцип единственной обязанности) SOLID проектирование
Open/Closed Principle (Принцип открытости/закрытости) SOLID проектирование

  Ваши вопросы присылайте по почте: info@dir.by  
Яндекс.Метрика