Принцип открытости-закрытости в Python с примерами

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

Что такое принцип открытости-закрытости в Python?

Принцип открытости-закрытости является одним из пяти составляющих принципа SOLID. Буква О в SOLID означает принцип «open-closed».

  • S – Принцип единой ответственности
  • O – Принцип открытости-закрытости
  • L – Принцип подстановки Лисков
  • I – Разделение интерфейса
  • D – Инверсии зависимостей

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

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

Рассмотрим следующий пример:

Пример принципа открытости-закрытости

class Person:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f'Person(name={self.name})'


class PersonStorage:
    def save_to_database(self, person):
        print(f'Save the {person} to database')

    def save_to_json(self, person):
        print(f'Save the {person} to a JSON file')


if __name__ == '__main__':
    person = Person('John Doe')
    storage = PersonStorage()
    storage.save_to_database(person)

В этом примере класс PersonStorage имеет два метода:

  • Метод save_to_database() сохраняет Person в базу данных.
  • Метод save_to_json() сохраняет Person в файл JSON.

Позже, если вы захотите сохранить объект Person в XML-файл, вам необходимо изменить класс PersonStorage. Это означает, что класс PersonStorage открыт не для расширения, а для модификации. Следовательно, это нарушает принцип открытости-закрытости.

Пример принципа открытости-закрытости

Чтобы класс PersonStorage соответствовал принципу открытости-закрытости; вам необходимо спроектировать классы так, чтобы, когда вам нужно сохранить объект Person в другом формате файла, вам не нужно было его изменять.

См. следующую диаграмму классов:

Практический пример принципа открытости-закрытости

  • Сначала определите абстрактный класс PersonStorage, содержащий абстрактный метод save():
from abc import ABC, abstractmethod

class PersonStorage(ABC):
    @abstractmethod
    def save(self, person):
        pass
  • Во-вторых, создайте два класса PersonDB и PersonJSON, которые сохранят объект Person в базе данных и файле JSON. Эти классы наследуются от класса PersonStorage:
class PersonDB(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to database')


class PersonJSON(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to a JSON file')
  • Чтобы сохранить объект Person в XML-файл, вы можете определить новый класс PersonXML, который наследуется от класса PersonStorage, следующим образом:

Сохранение объекта Person в XML-файл

class PersonXML(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to an XML file')
  • И вы можете сохранить объект Person в XML-файл, используя класс PersonXML:
if __name__ == '__main__':
    person = Person('John Doe')
    storage = PersonXML()
    storage.save(person)

Полный код:

from abc import ABC, abstractmethod


class Person:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f'Person(name={self.name})'


class PersonStorage(ABC):
    @abstractmethod
    def save(self, person):
        pass


class PersonDB(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to database')


class PersonJSON(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to a JSON file')


class PersonXML(PersonStorage):
    def save(self, person):
        print(f'Save the {person} to an XML file')


if __name__ == '__main__':
    person = Person('John Doe')
    storage = PersonXML()
    storage.save(person)
Похожие посты
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *