Принцип открытости/закрытости в 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
Перевод и адаптация: Екатерина Прохорова