Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЛР-6 / lab6

.py
Скачиваний:
0
Добавлен:
02.06.2026
Размер:
16.21 Кб
Скачать
from 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)
Соседние файлы в папке ЛР-6