89 lines
4.7 KiB
C++
89 lines
4.7 KiB
C++
/*
|
||
* api_client.h — HTTP-клиент, реализующий паттерн «Синглтон»
|
||
*
|
||
* ╔══════════════════════════════════════════════════════════════════╗
|
||
* ║ ПАТТЕРН «СИНГЛТОН» (Singleton) ║
|
||
* ╠══════════════════════════════════════════════════════════════════╣
|
||
* ║ Задача: гарантировать, что в приложении существует ровно ║
|
||
* ║ ОДИН экземпляр QNetworkAccessManager. Создание нескольких ║
|
||
* ║ менеджеров приводит к дублированию соединений и cookie-хранилищ.║
|
||
* ║ ║
|
||
* ║ Реализация (Meyers' Singleton): ║
|
||
* ║ • статическая локальная переменная в instance() ║
|
||
* ║ • конструктор объявлен private ║
|
||
* ║ • копирующий конструктор и operator= удалены (= delete) ║
|
||
* ╚══════════════════════════════════════════════════════════════════╝
|
||
*
|
||
* ApiClient также является «клиентом» паттерна «Адаптер»:
|
||
* он хранит указатель на IQuizAdapter и использует его
|
||
* для преобразования ответов сервера в Quiz-объекты,
|
||
* не зная о деталях реализации парсинга.
|
||
*
|
||
* Коммуникация с вызывающим кодом — через механизм сигналов Qt:
|
||
* quizzesReceived — список тестов успешно получен и десериализован
|
||
* quizReceived — один тест успешно получен и десериализован
|
||
* quizCreated — тест создан (POST)
|
||
* quizUpdated — тест обновлён (PUT)
|
||
* quizDeleted — тест удалён (DELETE)
|
||
* errorOccurred — произошла сетевая ошибка или ошибка парсинга
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#include <QObject> // базовый класс Qt с поддержкой сигналов/слотов
|
||
#include <QNetworkAccessManager> // выполняет HTTP-запросы асинхронно
|
||
#include <QJsonObject> // тело запросов POST/PUT
|
||
#include <QList> // контейнер для списка тестов
|
||
#include "quiz.h"
|
||
#include "iquiz_adapter.h"
|
||
|
||
class ApiClient : public QObject
|
||
{
|
||
/*
|
||
* Q_OBJECT — макрос Qt, активирует Meta-Object System:
|
||
* систему сигналов/слотов, rtti, tr() и пр.
|
||
* Обязателен для любого класса, использующего signals/slots.
|
||
*/
|
||
Q_OBJECT
|
||
|
||
public:
|
||
/*
|
||
* Единственная точка доступа к экземпляру (Singleton Access Point).
|
||
* Возвращает ссылку (не указатель), чтобы исключить проверку на nullptr.
|
||
*/
|
||
static ApiClient &instance();
|
||
|
||
// GET /api/quiz/ — получить все тесты
|
||
void fetchQuizzes();
|
||
|
||
// GET /api/quiz/:id/ — получить один тест по ID
|
||
void fetchQuiz(int id);
|
||
|
||
// POST /api/quiz/ — создать тест; тело запроса передаётся как QJsonObject
|
||
void createQuiz(const QJsonObject &data);
|
||
|
||
// PUT /api/quiz/:id/ — полностью обновить тест по ID
|
||
void updateQuiz(int id, const QJsonObject &data);
|
||
|
||
// DELETE /api/quiz/:id/ — удалить тест по ID
|
||
void deleteQuiz(int id);
|
||
|
||
signals:
|
||
void quizzesReceived(QList<Quiz> quizzes);
|
||
void quizReceived(Quiz quiz);
|
||
void quizCreated(Quiz quiz);
|
||
void quizUpdated(Quiz quiz);
|
||
void quizDeleted(QString message);
|
||
void errorOccurred(QString error);
|
||
|
||
private:
|
||
explicit ApiClient(QObject *parent = nullptr);
|
||
~ApiClient() override;
|
||
|
||
ApiClient(const ApiClient &) = delete;
|
||
ApiClient &operator=(const ApiClient &) = delete;
|
||
|
||
QNetworkAccessManager *m_manager;
|
||
IQuizAdapter *m_adapter;
|
||
QString m_baseUrl;
|
||
};
|