Принцип открытости/закрытости в Python
Из этого материала вы узнаете о принципе открытости/закрытости и о том, как расширять систему без прямого изменения существующего кода.
Введение в принцип открытости/закрытости
Это второй из пяти основных принципов объектно-ориентированного программирования:
S — принцип единой ответственности (Single responsibility Principle)
O — принцип открытости / закрытости (Open-closed Principle)
L — принцип подстановки Барбары Лисков (Liskov Substitution Principle)
I — принцип разделения интерфейса (Interface Segregation Principle)
D — принцип инверсии зависимостей (Dependency Inversion Principle)
Принцип открытости/закрытости гласит, что любой класс, метод и функция должны быть открыты для расширения, но закрыты для модификации.
Звучит противоречиво. Цель, вообще-то, благая – упростить добавление новых функций (или вариантов использования) в систему без непосредственного изменения существующего кода.
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()сохраняет информацию о сущности «человек» в базе данных;save_to_json()сохраняет данные о сущности в файл JSON.
Класс PersonStorage будет соответствовать второму принципу ООП, если его не нужно будет изменять всякий раз, когда возникнет необходимость сохранить объект Person в другой формат файла, например, в XML.
А как сделать так, чтобы класс соответствовал нашему принципу?
Во-первых, определите абстрактный класс PersonStorage, который содержит абстрактный метод save():
from abc import ABC, abstractmethod
class PersonStorage(ABC):
@abstractmethod
def save(self, person):
passЧтобы сохранить данные о сущности «человек» в XML-файл, вы можете определить новый класс PersonXML, который наследуется от класса 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')Теперь вы можете сохранить данные о сущности «человек» в 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 a XML file')
if __name__ == '__main__':
person = Person('John Doe')
storage = PersonXML()
storage.save(person)Заключение
Принцип открытости / закрытости позволяет спроектировать систему таким образом, чтобы её можно было расширять, но не изменять.
👉🏻Подписывайтесь на PythonTalk в Telegram 👈🏻
Источник: Python Tutorial
Перевод и адаптация: Екатерина Прохорова