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

ЛР-6 / ЯП №6

.pdf
Скачиваний:
1
Добавлен:
02.06.2026
Размер:
317.59 Кб
Скачать

Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования

ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР) Кафедра безопасности информационных систем (БИС)

ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ Отчет по лабораторной работе №6

по дисциплине «Языки программирования»

Студент гр.

_______

_______

Принял:

Доцент каф. КИБЭВС,

д.т.н., доцент

_______ Романов А. С.

_______

Томск 2026

 

Оглавление

Введение...................................................................................................................

3

Ход работы...............................................................................................................

4

Заключение ..............................................................................................................

6

Приложение А .........................................................................................................

7

2

Введение

Цель работы – знакомство с основными концепциями и приемами объектно-ориентированного анализа и проектирования, выработка практических навыков в построении модели предметной области и элементов модели проектирования. Код написан на ЯП Python.

3

Ход работы

Для данной лабораторной работы необходимо было разработать программу по варианту 19: Система управления уличным освещением на основе датчиков освещённости (рис 1.1). Листинг программы представлен в приложении А. Также была разработана UML-диаграмма, показывающая все связи классов (рис 1.2).

Рисунок 1.1 – Вывод для программы по варианту

4

Рисунок 1.2 – UML-диаграмма связей классов

5

Заключение

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

6

Приложение А

(обязательное)

Листинг кода для лабораторной работы

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: проверка

7

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)

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

8

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:

9

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_power: суммарная мощность

total_lights = 0# локальная переменная total_lights: суммарное число фонарей for zone in self._zones:# итерация по списку _zones

power = zone.get_total_power()# мощность текущей зоны total_power += power# накопление total_power total_lights += len(zone._lights)# накопление total_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)

10

Соседние файлы в папке ЛР-6