×
=0) { let js = text.slice(pos1, pos2); + '<\/' + "script" + '>'; arrText.push(js); // next pos1 = pos2; continue; } } } break; } return arrText; } function OpenDialog(parentDiv, urlContent) { parentDiv = document.getElementById('modal-background'); // new !!!!!!! parentDiv.appendChild(document.getElementById('modal-template')); document.getElementById('modal-background').style.display = "block"; document.getElementById('modal-template').style.display = "flex"; // !!!!! document.getElementById('modal-body').innerHTML = ""; post_url(urlContent, "", function(text_from_server) { var element = document.getElementById('modal-body'); element.innerHTML = text_from_server; // add scripts var arrJSText = get_scripts(text_from_server); for (var i=0; i
dir.by
Праздники ...
Праздники ...
День Святого Валентина (14 Февраля)
Концерты, выставки, цирки ...
Концерты, выставки, цирки ...
Спектакль "Трикстер клуб" г. Минск 14 января, 17 февраля 2026
Афишу
Спорт занятия ...
Спорт занятия ...
Занятия в тренажерном зале
Спорт занятие
Компьютеры, игры, программирование
Компьютеры, игры, программирование
Объявления ...
Объявления ...
Прокат детских электромобилей
Объявление
Форум (ваши вопросы, обсуждение)
Форум (ваши вопросы, обсуждение)
Search
Programming, development, testing
→
Паттерны, шаблоны проектирования | принципы ООП | рефакторинг кода
→
Open/Closed Principle (Принцип открытости/закрытости) SOLID проектирование
Looked at
5665
times
Open/Closed Principle (Принцип открытости/закрытости) SOLID проектирование
last updated: 19 October 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
и это расширение функциональности
Модификаций нет
Итог!
Наши классы соответствует
Принципу открытости/закрытости
← Previous topic
Single Responsibility Principle (Принцип единственной обязанности) SOLID проектирование
Your feedback ... Comments ...
Your Name
Your comment
(www links can only be added by a logged-in user)
+ Picture
Экскурсии по Москве: пешеходные, автобусные и речные прогулки на любой вкус
Объявления
Объявления
Введение
•
Что такое подкласс или дочерний класс или наследник класса? Что такое родительский класс ?
Принципы ООП
•
Что такое Объектно-ориентированное программирование? Принципы: абстрагирование, инкапсуляция, наследование, полиморфизм
Рефакторинг кода
•
Что такое рефакторинг кода ?
Шаблоны проектирования
Порождающие паттерны
•
Фабричный метод (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