工厂设计 C++/QtCreator

Posted

技术标签:

【中文标题】工厂设计 C++/QtCreator【英文标题】:Factory Design C++/QtCreator 【发布时间】:2021-05-01 15:16:40 【问题描述】:

我正在尝试实现工厂设计模式。我使用“Factory”类的静态成员函数,它创建并返回“Candy”的实例,但对用户隐藏了类模块的详细信息。

我的头文件贴在下面:

#ifndef CANDY_H
#define CANDY_H

#include <QColor>
#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QDebug>
#include <QLayoutItem>
#include <QIcon>
#include <QFont>

enum class CandyType Normal, Powerup;
enum class PowerUpType None, Wrapped, Striped, Sour;

class Candy : public QObject, public QGraphicsItem

    // this makes it so that we can emit signals
    Q_OBJECT

public:
    //static std::vector<CandyType> enum_vec;

    //Candy(QColor color, const int i, const int j);

    Candy();

    int get_i() const  return j_;   // inline member function
    int get_j() const  return i_;   // inline member function
    QColor get_color() const  return color_; 
    //CandyType get_candy_type() const  return candy_type_; 

    std::vector<Candy*> get_neighbors()  return neighbors_; 

    QRectF boundingRect() const override;
    QPainterPath shape() const override;

    void SwapCandy(Candy *c);

    void StoreNeighbors(std::vector<Candy*> neighbors_vec);

    void Poof();

    void setIJ(int i, int j);

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;

signals:
    void StoreSwapCandySelected(Candy *c);
    void SwapCandySelected(Candy *c);

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;

private:
  int i_;
  int j_;

  QColor color_;
  QFont myFont;
  bool next_state;
  static const int width_ = 35;
  std::vector<Candy*> neighbors_;
;  // class RegCandy
 // CANDY_H

/*INHERITED CLASS -- the functions that shoudl be different from parent
 * are the constructor and the mousepressevent. In addition some feilds
 * and getters are unnecessary and some added functions are used*/

class PowerUp : public Candy

    Q_OBJECT

public:
    static std::vector<PowerUpType> enum_vec;
    PowerUp() : Candy() 

    std::string CandyTypeToString() 
        if (powerup_type_ == PowerUpType::Wrapped) 
            return "Wrapped";
         else if (powerup_type_ == PowerUpType::Striped) 
            return "Striped";
         else 
            return "Sour";
        
    

    PowerUpType get_candy_type() const  return powerup_type_; 

    void setPUType(PowerUpType p_type) 
        this->powerup_type_ = p_type;
    

    void setColor(QColor color) 
        this->color_ = color;
    

    void setEmpty() 
        empty_ = true;
    

    void setFull() 
        empty_ = false;
    

    bool isEmpty()  return empty_; 

signals:
    void StorePowerUpSelected(PowerUp *p);

protected:
    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override 
        if (event->button() == Qt::LeftButton) 
            //qDebug() << QString::fromStdString(this->CandyTypeToString()) << ": " << this->get_i() << "," << this->get_j();
            emit StorePowerUpSelected(this);
        
        update();
    

private:
  int i_;
  int j_;
  PowerUpType powerup_type_;
  QColor color_;
  bool empty_ = true;;
  //bool next_state;
  static const int width_ = 35;

; //class PowerUp

class Factory 
public:

    /*~Factory() 
        if (c_type) 
            delete[] c_type;
            c_type = NULL;
        
    */
    static Candy* getCandy(CandyType type)  
        if (type == CandyType::Normal)
            return new Candy();
        else if (type == CandyType::Powerup)
            return new PowerUp();
        else return NULL;
    

;

#endif

目前我的 PowerUp 类继承自我的 Candy 类,我想使用 Factory::getCandy() 来创建每个对象的实例,但是当我尝试像这样调用静态方法 getCandy() 时:

PowerUp *p = Factory::getCandy(CandyType::Powerup);

我收到以下错误,“错误:无法使用 Candy * 类型的右值初始化 PowerUp * 类型的变量”

我认为通过让 'PowerUp' 类继承自 'Candy' 类,我可以将返回值 Candy* 存储在 PowerUp* 中,但是在对继承进行了更多思考之后,似乎逻辑如下,'每个 PowerUp 都是 Candy,但不是每个 Candy 都是 PowerUp',所以也许应该写下这行:

Candy *c = Factory::getCandy(CandyType::Powerup);

但是我需要'PowerUp'糖果有一些不同于超类的方法,所以我不知道如果我特别想要一个 PowerUp 实例,我为什么要将 Factory::getCandy() 的返回值存储在 Candy* 中*.

注意:它适用于使用以下行创建“Candy”实例: Candy *c = Factory::getCandy(CandyType::Normal)

我知道我的实现可能并不完美,这是我第一次尝试将工厂设计添加到我的代码中,但它似乎在我的程序中非常有用。非常感谢任何指针。提前谢谢!

【问题讨论】:

【参考方案1】:

你说:

但是我需要PowerUp 糖果有一些不同的方法 比超类,所以我不知道为什么我会存储回报 Factory::getCandy()Candy* 的值,如果我特别想要一个 PowerUp* 的实例。

如果这是真的,工厂是没有意义的,使用一个简单的构造函数。工厂的全部意义在于通过共享一个通用接口来抽象出细节(例如,您的Candy 实际上是PowerUp)。在您的情况下,如果应用程序知道它使用的特定类型并调用只有该类型具有的方法,则意味着没有抽象。

你可以:

    删除工厂并使用经典构造函数。 查看您的Candy 抽象,使PowerUp 成为真正的实现细节。最后,在调用代码的眼中,使用PowerUp 和任何其他类似Candy 的类型应该没有区别。

【讨论】:

谢谢!这帮助很大。我会选择(2),这样我仍然可以实现工厂。我仍然不清楚为什么在这种情况下我什至想要一个派生类? 实际上,我想通过声明虚方法(而不是添加新方法),我可以根据派生类的需要简单地更改函数体。 抽象是为了隐藏实现细节。在调用代码的眼中,这是一个以抽象方式说明应该发生什么的合约(即函数调用)。具体的派生类是用来说明应该如何发生的。对于调用代码来说,这是一个无趣的细节。 了解 S.O.L.I.D.更多关于这方面的原则。

以上是关于工厂设计 C++/QtCreator的主要内容,如果未能解决你的问题,请参考以下文章

工厂设计 C++/QtCreator

嵌入式C语言设计模式 --- 简单工厂模式

嵌入式C语言设计模式 --- 简单工厂模式

嵌入式C语言设计模式 --- 工厂方法模式

嵌入式C语言设计模式 --- 工厂方法模式

嵌入式C语言设计模式 --- 抽象工厂模式