#c #qt #design-patterns
#c #qt #шаблоны проектирования
Вопрос:
Мне было интересно, выполняет ли этот фрагмент кода все, что запрашивает шаблон проектирования чистого фабричного метода? Это подготовка к моему последнему модулю программирования, и мне просто нужно убедиться, что это правильное применение шаблона проектирования.
#include <QCoreApplication>
#include <QString>
#include <QDebug>
class Bread
{
public:
virtual void print() = 0;
};
class WhiteBread: public Bread
{
public:
void print() {
qDebug() << "White bread";
}
};
class BrownBread: public Bread
{
public:
void print() {
qDebug() << "Brown bread";
}
};
class BreadFactory {
public:
Bread* makeBread(QString type) {
if (type == "White bread")
return new WhiteBread();
else if (type == "Brown bread")
return new BrownBread();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
BreadFactory *breadFactory = new BreadFactory();
Bread *breadType;
breadType= breadFactory->makeBread("White bread");
breadType->print();
breadType = breadFactory->makeBread("Brown bread");
breadType->print();
return a.exec();
}
Комментарии:
1. Я думаю, что это называется «абстрактный фабричный метод». Если это то, что подразумевается, все в порядке. Но если имеется в виду действительно «чистый» (чисто виртуальный), то у вас, вероятно, должен быть абстрактный класс-предок с чисто виртуальным (без тела) фабричным методом и двумя наследующими конкретными классами с реализациями для этого метода с той же сигнатурой (включая абстрактный возвращаемый тип), но создающими объекты разных производных классовабстрактного возвращаемого типа фабричного метода.
2. Ваш — упрощенный вариант фабричного метода, и он практически бесполезен. Что делать, если новый производный объект yellow_bread должен быть включен без изменения кода заводского класса. Вам нужен метод на фабрике, который позволяет динамически регистрировать объекты.
3. кстати, отсутствует виртуальный деструктор, не весь путь возврата makeBread. и
unique_ptr
было бы лучше, чем необработанный указатель.4. Спасибо за советы, так должен ли я создать абстрактную фабрику по производству хлеба, которая обрабатывает логику, и клиента, который создает абстрактную фабрику? Может ли кто-нибудь привести мне пример этой реализации? У меня нет большого опыта в ООП
Ответ №1:
- Вам не нужно создавать экземпляр
BreadFactory
. Просто используйте статический метод.class BreadFactory { public: static Bread* makeBread( QString type ) { ... } }; //in main Bread *breadType = BreadFactory::makeBread( "White Bread"); breadType->print();
override
Для наглядности используйте ключевое слово c 11.class WhiteBread : public Bread { public: void print() override{ ...
- Используйте c 11
unique_ptr
среди интеллектуальных указателей.static unique_ptr<Bread> makeBread( QString type ) { if ( type == "White bread" ) return std::make_unique<WhiteBread>(); else if ( type == "Brown bread" ) return std::make_unique<BrownBread>(); else return nullptr; }
- Используйте
virtual
деструктор.class Bread { public: virtual void print() = 0; virtual ~Bread() {}; };
Ответ №2:
Реализация фабричного метода будет выглядеть следующим образом:
class BreadMaker
{
public:
virtual Bread* makeBread() = 0;
}
class WhiteBreadMaker : public BreadMaker
{
public:
Bread* makeBread();
}
// WhiteBreadMaker.cpp
Bread* WhiteBreadMaker::makeBread()
{
return new WhiteBread();
}
// ***Similarly for BrownBreadMaker
// main.cpp
int main()
{
BreadMaker *maker = new WhiteBreadMaker(); // or BrownBreadMaker
Bread *bread = maker->makeBread();
bread->print(); // prints "White Bread" or "Brown Bread" depending on the Factory class used.
}