Кашина_СП_ЛБ12
.docxМинистерство науки и высшего образования Российской Федерации Федеральное государственное бюджетное образовательное учреждение высшего образования
«Владимирский государственный университет
имени Александра Григорьевича и Николая Григорьевича Столетовых» (ВлГУ)
Колледж инновационных технологий и предпринимательства
КАФЕДРА ФИЗИКИ И ПРИКЛАДНОЙ МАТЕМАТИКИ
Лабораторная работа № 12
по дисциплине «Системное программирование»
на тему: «Шаблоны проектирования.»
Выполнил
студент группы ИПсп-123
Кашина Д. А.
Принял
Красильщикова В. В.
Владимир, 2026
Цель работы: получение практических навыков реализации шаблонов проектирования.
Задание:
Ход работы
person.h
#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <stdexcept>
using namespace std;
struct Person {
string lastName;
string firstName;
int age;
char gender;
Person(const string& last = "", const string& first = "",
int a = 0, char g = 'M')
: lastName(last), firstName(first), age(a), gender(g) {
if (a < 0 || a > 150) {
throw invalid_argument("Некорректный возраст! Возраст должен быть от 0 до 150 лет.");
}
if (g != 'M' && g != 'F' && g != 'm' && g != 'f') {
throw invalid_argument("Некорректный пол! Используйте 'M' или 'F'.");
}
if (g == 'm') gender = 'M';
if (g == 'f') gender = 'F';
}
};
#endif
person_tree.h
#ifndef PERSON_TREE_H
#define PERSON_TREE_H
#include "person.h"
#include "person_state.h"
#include <vector>
#include <stdexcept>
#include <map>
using namespace std;
class DuplicatePersonException : public runtime_error {
public:
DuplicatePersonException(const string& msg) : runtime_error(msg) {}
};
class PersonNotFoundException : public runtime_error {
public:
PersonNotFoundException(const string& msg) : runtime_error(msg) {}
};
class PersonTree {
private:
struct Node {
Person data;
PersonContext* stateContext;
Node* left;
Node* right;
Node(const Person& p);
~Node();
};
Node* root;
// Вспомогательные методы
Node* add(Node* node, const Person& person);
Node* remove(Node* node, const Person& person);
Node* findMin(Node* node);
void clear(Node* node);
void toArray(Node* node, vector<Person>& arr);
void toArrayWithStates(Node* node, vector<pair<Person, string>>& arr);
bool compareByKey(const Person& a, const Person& b);
bool equalsByKey(const Person& a, const Person& b);
Node* findByKey(Node* node, const Person& person);
bool searchByAge(Node* node, int age);
bool searchByLastName(Node* node, const string& lastName);
public:
PersonTree();
~PersonTree();
void add(const Person& person);
void remove(const Person& person);
bool existsByFullKey(const Person& person);
bool existsByAge(int age);
bool existsByLastName(const string& lastName);
vector<Person> getAll();
vector<pair<Person, string>> getAllWithStates();
bool isEmpty() const { return root == nullptr; }
string performActionOnPerson(const Person& person, const string& action);
vector<string> performActionOnAll(const string& action);
map<string, int> getStatesStatistics();
};
#endif
person_tree.cpp
#include "person_tree.h"
#include <iostream> // для отладки
PersonTree::Node::Node(const Person& p) : data(p), left(nullptr), right(nullptr) {
stateContext = new PersonContext(p.firstName + " " + p.lastName);
stateContext->setState(new HealthyState()); // По умолчанию здоров
}
PersonTree::Node::~Node() {
delete stateContext;
}
PersonTree::PersonTree() : root(nullptr) {}
PersonTree::~PersonTree() {
clear(root);
}
void PersonTree::clear(Node* node) {
if (!node) return;
clear(node->left);
clear(node->right);
delete node;
}
bool PersonTree::compareByKey(const Person& a, const Person& b) {
if (a.age != b.age) return a.age < b.age;
return a.lastName < b.lastName;
}
bool PersonTree::equalsByKey(const Person& a, const Person& b) {
return a.age == b.age && a.lastName == b.lastName;
}
PersonTree::Node* PersonTree::add(Node* node, const Person& person) {
if (!node) return new Node(person);
if (equalsByKey(person, node->data))
throw DuplicatePersonException("Человек с таким возрастом и фамилией уже существует!");
if (compareByKey(person, node->data))
node->left = add(node->left, person);
else
node->right = add(node->right, person);
return node;
}
void PersonTree::add(const Person& person) {
root = add(root, person);
}
PersonTree::Node* PersonTree::findMin(Node* node) {
while (node->left) node = node->left;
return node;
}
PersonTree::Node* PersonTree::remove(Node* node, const Person& person) {
if (!node) throw PersonNotFoundException("Человек с указанным возрастом и фамилией не найден!");
if (compareByKey(person, node->data))
node->left = remove(node->left, person);
else if (compareByKey(node->data, person))
node->right = remove(node->right, person);
else {
if (!node->left && !node->right) {
delete node;
return nullptr;
}
if (!node->left) {
Node* temp = node->right;
delete node;
return temp;
}
if (!node->right) {
Node* temp = node->left;
delete node;
return temp;
}
Node* minNode = findMin(node->right);
// СОХРАНЯЕМ состояние перед заменой
PersonContext* oldContext = node->stateContext;
node->data = minNode->data;
// СОХРАНЯЕМ состояние для нового узла
delete node->stateContext;
node->stateContext = new PersonContext(minNode->data.firstName + " " + minNode->data.lastName);
// КОПИРУЕМ состояние из minNode
string currentStateName = minNode->stateContext->getCurrentStateName();
if (currentStateName == "Здоров") {
node->stateContext->setState(new HealthyState());
}
else if (currentStateName == "Болеет") {
node->stateContext->setState(new SickState());
}
else if (currentStateName == "Работает") {
node->stateContext->setState(new WorkingState());
}
else if (currentStateName == "Учится") {
node->stateContext->setState(new StudyingState());
}
else {
node->stateContext->setState(new HealthyState());
}
node->right = remove(node->right, minNode->data);
}
return node;
}
void PersonTree::remove(const Person& person) {
root = remove(root, person);
}
PersonTree::Node* PersonTree::findByKey(Node* node, const Person& person) {
if (!node) return nullptr;
if (equalsByKey(person, node->data)) return node;
if (compareByKey(person, node->data)) return findByKey(node->left, person);
return findByKey(node->right, person);
}
bool PersonTree::existsByFullKey(const Person& person) {
return findByKey(root, person) != nullptr;
}
bool PersonTree::searchByAge(Node* node, int age) {
if (!node) return false;
if (node->data.age == age) return true;
return searchByAge(node->left, age) || searchByAge(node->right, age);
}
bool PersonTree::existsByAge(int age) {
return searchByAge(root, age);
}
bool PersonTree::searchByLastName(Node* node, const string& lastName) {
if (!node) return false;
if (node->data.lastName == lastName) return true;
return searchByLastName(node->left, lastName) || searchByLastName(node->right, lastName);
}
bool PersonTree::existsByLastName(const string& lastName) {
return searchByLastName(root, lastName);
}
void PersonTree::toArray(Node* node, vector<Person>& arr) {
if (!node) return;
toArray(node->left, arr);
arr.push_back(node->data);
toArray(node->right, arr);
}
vector<Person> PersonTree::getAll() {
vector<Person> arr;
toArray(root, arr);
return arr;
}
void PersonTree::toArrayWithStates(Node* node, vector<pair<Person, string>>& arr) {
if (!node) return;
toArrayWithStates(node->left, arr);
arr.push_back({ node->data, node->stateContext->getCurrentStateName() });
toArrayWithStates(node->right, arr);
}
vector<pair<Person, string>> PersonTree::getAllWithStates() {
vector<pair<Person, string>> arr;
toArrayWithStates(root, arr);
return arr;
}
string PersonTree::performActionOnPerson(const Person& person, const string& action) {
Node* node = findByKey(root, person);
if (!node) throw PersonNotFoundException("Человек не найден!");
// ОТЛАДКА: выводим текущее состояние
cout << "[DEBUG] Текущее состояние: " << node->stateContext->getCurrentStateName() << endl;
cout << "[DEBUG] Выполняем действие: " << action << endl;
string result = node->stateContext->performAction(action);
// ОТЛАДКА: выводим новое состояние
cout << "[DEBUG] Новое состояние: " << node->stateContext->getCurrentStateName() << endl;
return result;
}
vector<string> PersonTree::performActionOnAll(const string& action) {
vector<string> results;
vector<pair<Person, string>> persons = getAllWithStates();
for (auto& p : persons) {
Node* node = findByKey(root, p.first);
if (node) {
results.push_back(node->stateContext->performAction(action));
}
}
return results;
}
map<string, int> PersonTree::getStatesStatistics() {
map<string, int> stats;
vector<pair<Person, string>> persons = getAllWithStates();
for (auto& p : persons) {
stats[p.second]++;
}
return stats;
}
person_state.h
#ifndef PERSON_STATE_H
#define PERSON_STATE_H
#include <iostream>
#include <string>
using namespace std;
class PersonContext;
class PersonState {
public:
virtual ~PersonState() = default;
virtual string getActionDescription(const string& name, const string& action) const = 0;
virtual string getStateName() const = 0;
virtual PersonState* handleEvent(const string& event) = 0;
};
class PersonContext {
private:
PersonState* currentState;
string name;
public:
PersonContext(const string& personName);
~PersonContext();
void setState(PersonState* state);
string performAction(const string& action);
string getCurrentStateName() const;
string getName() const;
};
class HealthyState : public PersonState {
public:
string getActionDescription(const string& name, const string& action) const override;
string getStateName() const override;
PersonState* handleEvent(const string& event) override;
};
class SickState : public PersonState {
public:
string getActionDescription(const string& name, const string& action) const override;
string getStateName() const override;
PersonState* handleEvent(const string& event) override;
};
class WorkingState : public PersonState {
public:
string getActionDescription(const string& name, const string& action) const override;
string getStateName() const override;
PersonState* handleEvent(const string& event) override;
};
class StudyingState : public PersonState {
public:
string getActionDescription(const string& name, const string& action) const override;
string getStateName() const override;
PersonState* handleEvent(const string& event) override;
};
// RestState объявлен ТОЛЬКО ЗДЕСЬ
class RestState : public PersonState {
public:
string getActionDescription(const string& name, const string& action) const override;
string getStateName() const override;
PersonState* handleEvent(const string& event) override;
};
#endif
person_tree.cpp
#include "person_state.h"
PersonContext::PersonContext(const string& personName) : name(personName), currentState(nullptr) {}
PersonContext::~PersonContext() {
delete currentState;
}
void PersonContext::setState(PersonState* state) {
if (currentState) delete currentState;
currentState = state;
}
string PersonContext::performAction(const string& action) {
if (currentState) {
PersonState* newState = currentState->handleEvent(action);
if (newState != currentState) {
setState(newState);
}
return currentState->getActionDescription(name, action);
}
return "Состояние не установлено!";
}
string PersonContext::getCurrentStateName() const {
return currentState ? currentState->getStateName() : "Не установлено";
}
string PersonContext::getName() const {
return name;
}
// ============ HealthyState ============
string HealthyState::getActionDescription(const string& name, const string& action) const {
if (action == "walk") return name + " гуляет и остаётся здоровым!";
if (action == "work") return name + " начинает работать!";
if (action == "study") return name + " начинает учиться!";
if (action == "sick") return name + " заболел(а)!";
if (action == "treat") return name + " уже здоров(а), лечение не нужно!";
if (action == "rest") return name + " отдыхает!";
return name + " чувствует себя отлично!";
}
string HealthyState::getStateName() const {
return "Здоров";
}
PersonState* HealthyState::handleEvent(const string& event) {
if (event == "walk") return new HealthyState();
if (event == "work") return new WorkingState();
if (event == "study") return new StudyingState();
if (event == "sick") return new SickState();
if (event == "treat") return new HealthyState();
if (event == "rest") return new RestState();
return this;
}
// ============ SickState ============
string SickState::getActionDescription(const string& name, const string& action) const {
if (action == "walk") return name + " не может гулять, он(а) болеет!";
if (action == "work") return name + " не может работать из-за болезни!";
if (action == "study") return name + " не может учиться из-за болезни!";
if (action == "sick") return name + " уже болеет!";
if (action == "treat") return name + " лечится и выздоравливает!";
if (action == "rest") return name + " отдыхает, чтобы выздороветь!";
return name + " плохо себя чувствует.";
}
string SickState::getStateName() const {
return "Болеет";
}
PersonState* SickState::handleEvent(const string& event) {
if (event == "walk") return this;
if (event == "work") return this;
if (event == "study") return this;
if (event == "sick") return this;
if (event == "treat") return new HealthyState();
if (event == "rest") return new RestState();
return this;
}
// ============ WorkingState ============
string WorkingState::getActionDescription(const string& name, const string& action) const {
if (action == "walk") return name + " не может гулять, он(а) работает!";
if (action == "work") return name + " уже работает!";
if (action == "study") return name + " не может учиться, он(а) работает!";
if (action == "sick") return name + " заболел(а) на работе!";
if (action == "treat") return name + " нужно лечиться, а не работать!";
if (action == "rest") return name + " отдыхает после работы!";
return name + " занят работой.";
}
string WorkingState::getStateName() const {
return "Работает";
}
PersonState* WorkingState::handleEvent(const string& event) {
if (event == "walk") return this;
if (event == "work") return this;
if (event == "study") return this;
if (event == "sick") return new SickState();
if (event == "treat") return this;
if (event == "rest") return new RestState();
return this;
}
// ============ StudyingState ============
string StudyingState::getActionDescription(const string& name, const string& action) const {
if (action == "walk") return name + " не может гулять, он(а) учится!";
if (action == "work") return name + " не может работать, он(а) учится!";
if (action == "study") return name + " уже учится!";
if (action == "sick") return name + " заболел(а) из-за учёбы!";
if (action == "treat") return name + " нужно лечиться, а не учиться!";
if (action == "rest") return name + " отдыхает после учёбы!";
return name + " занят учёбой.";
}
string StudyingState::getStateName() const {
return "Учится";
}
PersonState* StudyingState::handleEvent(const string& event) {
if (event == "walk") return this;
if (event == "work") return this;
if (event == "study") return this;
if (event == "sick") return new SickState();
if (event == "treat") return this;
if (event == "rest") return new RestState();
return this;
}
// ============ RestState - ТОЛЬКО РЕАЛИЗАЦИЯ МЕТОДОВ, НЕ ОПРЕДЕЛЕНИЕ КЛАССА! ============
string RestState::getActionDescription(const string& name, const string& action) const {
if (action == "walk") return name + " гуляет и отдыхает!";
if (action == "work") return name + " начинает работать после отдыха!";
if (action == "study") return name + " начинает учиться после отдыха!";
if (action == "sick") return name + " заболел(а) во время отдыха!";
if (action == "treat") return name + " лечится, но лучше отдыхать!";
if (action == "rest") return name + " уже отдыхает!";
return name + " наслаждается отдыхом.";
}
string RestState::getStateName() const {
return "Отдыхает";
}
PersonState* RestState::handleEvent(const string& event) {
if (event == "walk") return new HealthyState();
if (event == "work") return new WorkingState();
if (event == "study") return new StudyingState();
if (event == "sick") return new SickState();
if (event == "treat") return new HealthyState();
if (event == "rest") return this;
return this;
}
person_decorator.h
#ifndef PERSON_DECORATOR_H
#define PERSON_DECORATOR_H
#include "person.h"
#include <iostream>
using namespace std;
// Базовый интерфейс
class PersonInterface {
public:
virtual ~PersonInterface() = default;
virtual void describe() const = 0;
virtual string getInfo() const = 0;
};
// Адаптер для структуры Person
class PersonAdapter : public PersonInterface {
protected:
Person person;
public:
PersonAdapter(const Person& p) : person(p) {}
void describe() const override {
cout << getInfo();
}
string getInfo() const override {
return "Человек: " + person.lastName + " " + person.firstName +
", возраст: " + to_string(person.age) +
", пол: " + (person.gender == 'M' ? "Мужской" : "Женский");
}
Person getPerson() const {
return person;
}
};
// Базовый класс декоратора
class PersonDecorator : public PersonInterface {
protected:
PersonInterface* wrapped;
public:
PersonDecorator(PersonInterface* p) : wrapped(p) {}
virtual ~PersonDecorator() {
delete wrapped;
}
void describe() const override {
wrapped->describe();
}
string getInfo() const override {
return wrapped->getInfo();
}
};
// Конкретный декоратор: Студент
class StudentDecorator : public PersonDecorator {
private:
string university;
string group;
double averageGrade;
public:
StudentDecorator(PersonInterface* p, const string& uni, const string& grp, double grade)
: PersonDecorator(p), university(uni), group(grp), averageGrade(grade) {}
void describe() const override {
cout << getInfo();
}
string getInfo() const override {
return PersonDecorator::getInfo() +
"\n - Студент университета: " + university +
"\n - Группа: " + group +
"\n - Средний балл: " + to_string(averageGrade);
}
};
// Конкретный декоратор: Работник
class WorkerDecorator : public PersonDecorator {
private:
string company;
string position;
double salary;
public:
WorkerDecorator(PersonInterface* p, const string& comp, const string& pos, double sal)
: PersonDecorator(p), company(comp), position(pos), salary(sal) {}
void describe() const override {
cout << getInfo();
}
string getInfo() const override {
return PersonDecorator::getInfo() +
"\n - Работник компании: " + company +
"\n - Должность: " + position +
"\n - Зарплата: " + to_string(salary) + " руб.";
}
};
// Конкретный декоратор: Спортсмен
class AthleteDecorator : public PersonDecorator {
private:
string sport;
string rank;
int medalsCount;
public:
AthleteDecorator(PersonInterface* p, const string& sp, const string& r, int medals)
: PersonDecorator(p), sport(sp), rank(r), medalsCount(medals) {}
void describe() const override {
cout << getInfo();
}
string getInfo() const override {
return PersonDecorator::getInfo() +
"\n - Спортсмен, вид спорта: " + sport +
"\n - Разряд: " + rank +
"\n - Количество медалей: " + to_string(medalsCount);
}
};
#endif
person_builder.h
#ifndef PERSON_BUILDER_H
#define PERSON_BUILDER_H
#include "person.h"
// Строитель для создания Person
class PersonBuilder {
private:
string lastName;
string firstName;
int age;
char gender;
public:
PersonBuilder() : lastName(""), firstName(""), age(0), gender('M') {}
PersonBuilder& setLastName(const string& last) {
lastName = last;
return *this;
}
PersonBuilder& setFirstName(const string& first) {
firstName = first;
return *this;
}
PersonBuilder& setAge(int a) {
age = a;
return *this;
}
PersonBuilder& setGender(char g) {
gender = g;
return *this;
}
Person build() {
return Person(lastName, firstName, age, gender);
}
};
// Директор для удобного создания типовых Person
class PersonDirector {
public:
static Person createStudent(const string& last, const string& first, int age) {
return PersonBuilder()
.setLastName(last)
.setFirstName(first)
.setAge(age)
.setGender('M')
.build();
}
static Person createTeacher(const string& last, const string& first, int age) {
return PersonBuilder()
.setLastName(last)
.setFirstName(first)
.setAge(age)
.setGender('F')
.build();
}
static Person createChild(const string& last, const string& first, int age) {
return PersonBuilder()
.setLastName(last)
.setFirstName(first)
.setAge(age)
.setGender('M')
.build();
}
};
#endif
main.cpp
#include <iostream>
#include <iomanip>
#include <windows.h>
#include <limits>
#include <vector>
#include "person_tree.h"
using namespace std;
// ==================== ФУНКЦИИ ВВОДА/ВЫВОДА ====================
void setRussianConsole() {
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
}
void clearInput() {
cin.clear();
cin.ignore(10000, '\n');
}
void clearScreen() {
system("cls");
}
int inputAge() {
int age;
while (true) {
cout << "Введите возраст (0-150): ";
if (cin >> age) {
if (age >= 0 && age <= 150) return age;
cout << "Ошибка! Возраст должен быть от 0 до 150.\n";
}
else {
cout << "Ошибка! Введите целое число.\n";
clearInput();
}
}
}
char inputGender() {
char gender;
while (true) {
cout << "Введите пол (M/F): ";
cin >> gender;
if (gender == 'M' || gender == 'm' || gender == 'F' || gender == 'f') {
return toupper(gender);
}
cout << "Ошибка! Введите 'M' или 'F'.\n";
clearInput();
}
}
string inputString(const string& prompt) {
string str;
while (true) {
cout << prompt;
cin >> str;
if (!str.empty()) return str;
cout << "Ошибка! Строка не может быть пустой.\n";
}
}
Person inputPerson() {
Person p;
p.lastName = inputString("Введите фамилию: ");
p.firstName = inputString("Введите имя: ");
p.age = inputAge();
p.gender = inputGender();
return p;
}
Person inputPersonKey() {
Person p;
p.lastName = inputString("Введите фамилию: ");
p.age = inputAge();
return p;
}
void printTableHeader() {
cout << "+--------------+------------+--------+----------+------------------+\n";
cout << "| " << left << setw(12) << "Фамилия"
<< " | " << setw(10) << "Имя"
<< " | " << setw(6) << "Возраст"
<< " | " << setw(8) << "Пол"
<< " | " << setw(16) << "Состояние"
<< " |\n";
cout << "+--------------+------------+--------+----------+------------------+\n";
}
void printPersonRow(const Person& p, const string& state) {
cout << "| " << left << setw(12) << p.lastName
<< " | " << setw(10) << p.firstName
<< " | " << setw(6) << p.age
<< " | " << setw(8) << (p.gender == 'M' ? "Муж" : "Жен")
<< " | " << setw(16) << state
<< " |\n";
cout << "+--------------+------------+--------+----------+------------------+\n";
}
void printAllPersons(PersonTree& tree) {
vector<pair<Person, string>> persons = tree.getAllWithStates();
if (persons.empty()) {
cout << "\n*** В базе данных нет людей ***\n";
return;
}
cout << "\n==================== ВСЕ ЛЮДИ ====================\n";
printTableHeader();
for (const auto& p : persons) {
printPersonRow(p.first, p.second);
}
cout << "Всего людей: " << persons.size() << "\n";
}
string getActionChoice() {
cout << "\nВыберите действие:\n";
cout << " 1. Гулять (walk)\n";
cout << " 2. Работать (work)\n";
cout << " 3. Учиться (study)\n";
cout << " 4. Болеть (sick)\n";
cout << " 5. Лечиться (treat)\n";
cout << " 6. Отдыхать (rest)\n";
cout << "Ваш выбор: ";
int choice;
cin >> choice;
switch (choice) {
case 1: return "walk";
case 2: return "work";
case 3: return "study";
case 4: return "sick";
case 5: return "treat";
case 6: return "rest";
default: return "walk";
}
}
// ==================== ДЕМОНСТРАЦИЯ ПАТТЕРНОВ ====================
void demoBuilder() {
clearScreen();
cout << "\n========== ПАТТЕРН «СТРОИТЕЛЬ» (BUILDER) ==========\n\n";
class Builder {
string last, first;
int age;
char gender;
public:
Builder() : last(""), first(""), age(0), gender('M') {}
Builder& setLast(string l) { last = l; return *this; }
Builder& setFirst(string f) { first = f; return *this; }
Builder& setAge(int a) { age = a; return *this; }
Builder& setGender(char g) { gender = g; return *this; }
Person build() { return Person(last, first, age, gender); }
};
Person p1 = Builder().setLast("Сидоров").setFirst("Алексей").setAge(20).setGender('M').build();
Person p2 = Builder().setLast("Петрова").setFirst("Мария").setAge(19).setGender('F').build();
cout << "Создано через Builder:\n";
cout << " " << p1.lastName << " " << p1.firstName << ", " << p1.age << " лет\n";
cout << " " << p2.lastName << " " << p2.firstName << ", " << p2.age << " лет\n";
cout << "\nПреимущество: пошаговое создание объекта\n";
}
void demoDecorator() {
clearScreen();
cout << "\n========== ПАТТЕРН «ДЕКОРАТОР» (DECORATOR) ==========\n\n";
class Info {
public:
virtual ~Info() {}
virtual string get() const = 0;
};
class SimpleInfo : public Info {
Person p;
public:
SimpleInfo(const Person& person) : p(person) {}
string get() const override {
return p.lastName + " " + p.firstName + ", " + to_string(p.age) + " лет";
}
};
class StudentDecorator : public Info {
Info* wrapped;
public:
StudentDecorator(Info* w) : wrapped(w) {}
~StudentDecorator() { delete wrapped; }
string get() const override {
return wrapped->get() + " [Студент МГУ]";
}
};
Person test("Иванов", "Иван", 25, 'M');
Info* basic = new SimpleInfo(test);
cout << "Базовый: " << basic->get() << endl;
Info* student = new StudentDecorator(basic);
cout << "С декором: " << student->get() << endl;
delete student;
}
// ==================== ГЛАВНОЕ МЕНЮ ====================
void showMenu() {
cout << "\n";
cout << "+========================================================+\n";
cout << "| СИСТЕМА УПРАВЛЕНИЯ ЛЮДЬМИ |\n";
cout << "| (паттерны: Состояние, Строитель, Декоратор) |\n";
cout << "+========================================================+\n";
cout << "| 1. Добавить человека |\n";
cout << "| 2. Удалить человека |\n";
cout << "| 3. Найти по возрасту+фамилии |\n";
cout << "| 4. Найти по возрасту |\n";
cout << "| 5. Найти по фамилии |\n";
cout << "| 6. Показать всех |\n";
cout << "+========================================================+\n";
cout << "| 7. ПАТТЕРН «СОСТОЯНИЕ» - действие над человеком |\n";
cout << "| 8. ПАТТЕРН «СТРОИТЕЛЬ» - демонстрация |\n";
cout << "| 9. ПАТТЕРН «ДЕКОРАТОР» - демонстрация |\n";
cout << "+========================================================+\n";
cout << "| 0. Выход |\n";
cout << "+========================================================+\n";
cout << "Ваш выбор: ";
}
// ==================== MAIN ====================
int main() {
setRussianConsole();
PersonTree tree;
int choice;
// Тестовые данные
try {
tree.add(Person("Иванов", "Иван", 25, 'M'));
tree.add(Person("Петрова", "Мария", 30, 'F'));
tree.add(Person("Сидоров", "Алексей", 25, 'M'));
cout << "\n*** Добавлены тестовые данные ***\n";
}
catch (const exception& e) {
cout << "Ошибка: " << e.what() << endl;
}
do {
showMenu();
if (!(cin >> choice)) {
cout << "Ошибка! Введите число.\n";
clearInput();
continue;
}
try {
switch (choice) {
case 1: {
clearScreen();
cout << "\n--- ДОБАВЛЕНИЕ ЧЕЛОВЕКА ---\n";
Person p = inputPerson();
tree.add(p);
cout << "\n*** Человек добавлен! ***\n";
break;
}
case 2: {
clearScreen();
cout << "\n--- УДАЛЕНИЕ ЧЕЛОВЕКА ---\n";
Person p = inputPersonKey();
tree.remove(p);
cout << "\n*** Человек удалён! ***\n";
break;
}
case 3: {
clearScreen();
cout << "\n--- ПОИСК ПО КЛЮЧУ ---\n";
Person p = inputPersonKey();
if (tree.existsByFullKey(p)) {
cout << "\n*** Человек НАЙДЕН! ***\n";
}
else {
cout << "\n*** Человек НЕ НАЙДЕН ***\n";
}
break;
}
case 4: {
clearScreen();
cout << "\n--- ПОИСК ПО ВОЗРАСТУ ---\n";
int age = inputAge();
if (tree.existsByAge(age)) {
cout << "\n*** Есть человек с возрастом " << age << " лет! ***\n";
}
else {
cout << "\n*** Нет человека с возрастом " << age << " лет! ***\n";
}
break;
}
case 5: {
clearScreen();
cout << "\n--- ПОИСК ПО ФАМИЛИИ ---\n";
string last = inputString("Введите фамилию: ");
if (tree.existsByLastName(last)) {
cout << "\n*** Есть человек с фамилией '" << last << "'! ***\n";
}
else {
cout << "\n*** Нет человека с фамилией '" << last << "'! ***\n";
}
break;
}
case 6: {
clearScreen();
printAllPersons(tree);
break;
}
case 7: {
clearScreen();
cout << "\n========== ПАТТЕРН «СОСТОЯНИЕ» ==========\n\n";
vector<pair<Person, string>> persons = tree.getAllWithStates();
if (persons.empty()) {
cout << "*** Нет людей! ***\n";
break;
}
cout << "Доступные люди:\n";
printTableHeader();
for (const auto& p : persons) {
printPersonRow(p.first, p.second);
}
cout << "\nВыберите человека:\n";
Person p = inputPersonKey();
if (!tree.existsByFullKey(p)) {
cout << "\n*** Человек не найден! ***\n";
break;
}
string action = getActionChoice();
string result = tree.performActionOnPerson(p, action);
cout << "\n============================================\n";
cout << "РЕЗУЛЬТАТ: " << result << "\n";
cout << "============================================\n";
break;
}
case 8: {
demoBuilder();
break;
}
case 9: {
demoDecorator();
break;
}
case 0: {
clearScreen();
cout << "\n*** Выход из программы... ***\n";
break;
}
default: {
cout << "\n*** Неверный выбор! ***\n";
break;
}
}
}
catch (DuplicatePersonException& e) {
cout << "\n!!! ОШИБКА: " << e.what() << " !!!\n";
}
catch (PersonNotFoundException& e) {
cout << "\n!!! ОШИБКА: " << e.what() << " !!!\n";
}
catch (exception& e) {
cout << "\n!!! ОШИБКА: " << e.what() << " !!!\n";
}
if (choice != 0 && choice != 6 && choice != 8 && choice != 9) {
cout << "\nНажмите Enter для продолжения...";
cin.ignore();
cin.get();
}
} while (choice != 0);
return 0;
}
Диаграмма UML
Вывод: в ходе лабораторной работы получены практические навыки реализации шаблонов проектирования
