Добавил:
omninoy
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:ЛР-6 / lab6
.pyfrom abc import ABC, abstractmethod
from typing import List, Set
from datetime import time
# интерфейс — контракт для классов, которые можно включать/выключать
class Switchable(ABC):# абстрактный класс-интерфейс Switchable
@abstractmethod# декоратор: метод обязателен к реализации
def turn_on(self) -> None:# метод turn_on: включить устройство
pass
@abstractmethod# декоратор: метод обязателен к реализации
def turn_off(self) -> None:# метод turn_off: выключить устройство
pass
@abstractmethod# декоратор: метод обязателен к реализации
def is_on(self) -> bool:# метод is_on: проверить состояние включения
pass
#АБСТРАКТНЫЙ КЛАСС
# базовый класс для всех устройств системы SOLID-I Если бы Switchable был частью Device — LightSensor был бы вынужден иметь пустые методы turn_on()/turn_off()
class Device(ABC):# абстрактный класс Device, наследник ABC
def __init__(self, device_id: str, name: str):# конструктор Device: принимает id и имя
self._device_id = device_id
self._name = name # хочешь добавить новое устройство? Создаёшь класс, наследуешь Device, реализуешь get_status_report() — не трогаешь существующий код.
self.__status = "active"# SOLID-O
def get_id(self) -> str:# селектор get_id: получить идентификатор
return self._device_id
def get_name(self) -> str:# селектор get_name: получить название
return self._name
@abstractmethod# декоратор: абстрактный метод
#Полиморфизм — это свойство системы использовать объекты с одинаковым интерфейсом без информации о типе и внутренней структуре объекта.
def get_status_report(self) -> str:# метод get_status_report: отчёт о состоянии
pass# реализация обязательна в подклассах
#ПРОИЗВОДНЫЕ КЛАССЫ(Наследование)
class LightFixture(Device, Switchable):# класс LightFixture: наследник Device, реализация Switchable
def __init__(self, device_id: str, name: str, power_watts: float):# конструктор LightFixture
super().__init__(device_id, name)# вызов конструктора базового класса Device
self._power_watts = power_watts
self.__is_on = False
self._brightness = 100
def turn_on(self) -> None:
self.__is_on = True
print(f"светильник '{self._name}' ВКЛЮЧЕН")
def turn_off(self) -> None:
self.__is_on = False
print(f"светильник '{self._name}' ВЫКЛЮЧЕН")
def is_on(self) -> bool:# реализация метода интерфейса Switchable: проверка
return self.__is_on
def get_status_report(self) -> str:# реализация абстрактного метода Device: отчёт
state = "ВКЛ" if self.__is_on else "ВЫКЛ"
return f"светильник {self._name}: {state}, {self._power_watts}Вт, яркость {self._brightness}%"
def set_brightness(self, level: int) -> None:# модификатор set_brightness: изменить яркость
self._brightness = max(0, min(100, level))
print(f"яркость '{self._name}' установлена на {self._brightness}%")
def get_power(self) -> float:# селектор get_power: текущее потребление
if not self.__is_on:
return 0.0
return self._power_watts * (self._brightness / 100.0)
def __del__(self) -> None:pass
class LightSensor(Device):# класс LightSensor: наследник Device
def __init__(self, device_id: str, name: str, threshold: float):# конструктор LightSensor
super().__init__(device_id, name)# вызов конструктора базового класса Device
self._threshold = threshold
self.__current_lux = 0.0
# ТОЛЬКО измеряет свет
# SOLID- S отвечает только за одно
def read_light_level(self) -> float:# селектор read_light_level: прочитать освещённость
return self.__current_lux
def set_light_level(self, lux: float) -> None:# модификатор set_light_level: задать освещённость
self.__current_lux = lux
def is_dark(self) -> bool:# метод is_dark: проверка "темно ли?"
return self.__current_lux < self._threshold
def get_status_report(self) -> str:# реализация абстрактного метода Device: отчёт
return f"датчик {self._name}: {self.__current_lux:.1f} люкс (порог: {self._threshold} люкс)"
def calibrate(self, new_threshold: float) -> None:# модификатор calibrate: калибровка порога
self._threshold = new_threshold
print(f"датчик '{self._name}' откалиброван: порог = {self._threshold} люкс")
#Композиция
# класс LightingSchedule: часть StreetLight, не существует отдельно
class LightingSchedule:# класс LightingSchedule: расписание работы фонаря
def __init__(self, on_time: time, off_time: time):# конструктор LightingSchedule: время вкл/выкл
self._on_time = on_time
self._off_time = off_time
self._enabled = True
def is_active_time(self, current_time: time) -> bool:# метод is_active_time: проверка попадания во временной интервал
if not self._enabled:
return False
if self._on_time <= self._off_time:
return self._on_time <= current_time <= self._off_time
else:
return current_time >= self._on_time or current_time <= self._off_time
# Ассоциация
# класс StreetLight: ассоциирован с LightFixture и LightSensor (1 к 1)
class StreetLight:# класс StreetLight: уличный фонарь
def __init__(self, light_id: str, location: str, fixture: LightFixture, sensor: LightSensor):# конструктор
self._light_id = light_id
self._location = location
self._sensor = sensor# ассоциация: ссылка на объект LightSensor
self._fixture = fixture# ассоциация: ссылка на объект LightFixture
self._schedule = LightingSchedule(# композиция: создание LightingSchedule внутри StreetLight
on_time=time(20, 0),
off_time=time(6, 0)
)
self._auto_mode = True
def update(self, current_time: time) -> None:# метод update: основная бизнес-логика обновления
print(f"\nобновление фонаря '{self._light_id}' ({self._location})")
print(f"датчик: {self._sensor.get_status_report()}")
if self._auto_mode:
if self._sensor.is_dark():
self._fixture.turn_on()
else:
self._fixture.turn_off()
else:
if self._schedule.is_active_time(current_time):
self._fixture.turn_on()
else:
self._fixture.turn_off()
print(f"{self._fixture.get_status_report()}")
def get_power_consumption(self) -> float:
return self._fixture.get_power()
# Агрегация
# класс LightingZone: агрегирует StreetLight (части могут существовать отдельно)
class LightingZone:# класс LightingZone: зона освещения
def __init__(self, zone_id: str, zone_name: str):# конструктор LightingZone
self._zone_id = zone_id
self._zone_name = zone_name
self._lights: Set[StreetLight] = set()# агрегация: множество StreetLight (пустое по умолчанию)
def add_light(self, light: StreetLight) -> None:
self._lights.add(light)
print(f"фонарь '{light._light_id}' добавлен в зону '{self._zone_name}'")
def remove_light(self, light: StreetLight) -> None:
self._lights.discard(light)
print(f"фонарь '{light._light_id}' удалён из зоны '{self._zone_name}'")
def get_total_power(self) -> float:
return sum(light.get_power_consumption() for light in self._lights)
def update_all(self, current_time: time) -> None:
for light in self._lights:
light.update(current_time)
# Зависимость <<use>>
# класс LightingController: зависит от LightingZone (принимает как параметр)
class LightingController:# SOLID-D LightingController не зависит от LightFixture/LightSensor
def __init__(self, controller_name: str):# конструктор LightingController
self._name = controller_name
self._zones: List[LightingZone] = []
def add_zone(self, zone: LightingZone) -> None:
self._zones.append(zone)
def monitor_zone(self, zone: LightingZone) -> None:
print(f"зона: {zone._zone_name} ({len(zone._lights)} фонарей)")
print(f"общее потребление: {zone.get_total_power():.2f} Вт")
for light in zone._lights:
print(f"{light._light_id}: {light._location}")
def system_report(self) -> None:# метод system_report: отчёт по всей системе (зависимость)
total_power = 0.0
total_lights = 0
for zone in self._zones:# итерация по списку _zones
power = zone.get_total_power()
total_power += power
total_lights += len(zone._lights)
print(f"{zone._zone_name}: {power:.2f} Вт")
print(f"\nИТОГО: {total_lights} фонарей, {total_power:.2f} Вт")
#SOLID
# S Single Responsibility (Принцип единственной ответственности) Каждый класс должен отвечать только за одну вещь.
# O Open/Closed (Принцип открытости/закрытости) Открыт для расширения, закрыт для изменения.
# L Liskov Substitution (Принцип подстановки Лисков) Объект подкласса должен заменять объект базового класса без нарушения работы программы.
# I Interface Segregation (Принцип разделения интерфейса) Клиенты не должны зависеть от методов, которые они не используют.
# D Dependency Inversion (Принцип инверсии зависимостей) Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракций.
#ДЕМОНСТРАЦИЯ
# создание светильников (экземпляры LightFixture)
fixture1 = LightFixture("LF-001", "LED-Уличный-150", 150.0)
fixture2 = LightFixture("LF-002", "LED-Уличный-100", 100.0)
fixture3 = LightFixture("LF-003", "LED-Парк-80", 80.0)
# создание датчиков (экземпляры LightSensor)
sensor1 = LightSensor("SN-001", "Датчик-Центр", 30.0)
sensor2 = LightSensor("SN-002", "Датчик-Север", 25.0)
sensor3 = LightSensor("SN-003", "Датчик-Парк", 35.0)
# демонстрация полиморфизма: список объектов разных классов, общий базовый Device
devices: List[Device] = [fixture1, sensor1, fixture2, sensor2] # LightFixture и LightSensor — потомки Device Оба реализуют get_status_report()
for device in devices: # Можно подставить LightSensor вместо Device — код for device in devices не сломается
print(f"{device.get_status_report()}") #SOLID-L
# создание фонарей (ассоциация: передача готовых объектов)
street_light1 = StreetLight("SL-001", "ул. Ленина, 15", fixture1, sensor1)
street_light2 = StreetLight("SL-002", "ул. Ленина, 45", fixture2, sensor2)
street_light3 = StreetLight("SL-003", "парк Горького", fixture3, sensor3)
# создание зон (агрегация: фонари существуют отдельно)
central_zone = LightingZone("Z-01", "Центральный район")
north_zone = LightingZone("Z-02", "Северный район")
central_zone.add_light(street_light1) # агрегация: добавление street_light1 в central_zone
central_zone.add_light(street_light2) # агрегация: добавление street_light2 в central_zone
north_zone.add_light(street_light3) # агрегация: добавление street_light3 в north_zone
# демонстрация низкая освещённость (темно)
sensor1.set_light_level(10.0)
sensor2.set_light_level(15.0)
sensor3.set_light_level(5.0)
current_time = time(21, 30)
central_zone.update_all(current_time)
north_zone.update_all(current_time)
# создание контроллера (зависимость)
controller = LightingController("Главный контроллер") # объект controller: контроллер системы
controller.add_zone(central_zone)
controller.add_zone(north_zone)
controller.monitor_zone(central_zone) # зависимость: мониторинг central_zone
controller.system_report() # зависимость: отчёт по всей системе
# дополнительные методы производных классов
fixture1.set_brightness(75)
sensor1.calibrate(20.0)
# демонстрация: высокая освещённость (светло)
sensor1.set_light_level(150.0)
sensor2.set_light_level(200.0)
sensor3.set_light_level(120.0)
current_time = time(9, 0)
central_zone.update_all(current_time)
north_zone.update_all(current_time)
controller.system_report()
# демонстрация композиции: расписание — часть фонаря
print(f"\nКОМПОЗИЦИЯ: фонарь {street_light1._light_id} имеет расписание {street_light1._schedule._on_time}-{street_light1._schedule._off_time}")
# демонстрация агрегации: удаление фонаря из зоны (фонарь продолжает существовать)
central_zone.remove_light(street_light2) # удаление street_light2 из central_zone
print(f"фонарь '{street_light2._light_id}' всё ещё существует: {street_light2._location}") # объект жив
class a:
def __init__(self):
self.name = 'a'
class b(a):
def __init__(self):
self.name = 'b'
class c(b):
def __init__(self):
self.name = 'c'
def getinfoc(self, name) -> str:
return name
obj = c()
print(obj.name) 