简体   繁体   中英

Factory Design C++/QtCreator

I am trying to implement factory design pattern. I use a static member-function of the class 'Factory' which creates and returns instances of 'Candy', but hides the details of class modules from user.

My header file is pasted below:

#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

Currently my PowerUp class inherits from my Candy class and I want to use Factory::getCandy() to create instances of each object, however when I try to call on the static method getCandy() like this:

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

I get the following error, 'error: cannot initialize a variable of type PowerUp * with an rvalue of type Candy *'

I thought that by making the 'PowerUp' class inherit from the 'Candy' class that I could store the return value Candy* in PowerUp*, but after thinking a little more about inheritance it seems the logic follows something like, 'Every PowerUp is a Candy, but not every Candy is a PowerUp' and so perhaps the line should be written:

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

However I need the 'PowerUp' candies to have some different methods than the superclass, so I do not know why I would store the return value of Factory::getCandy() in Candy* if I specifically want an instance of PowerUp*.

Note: it works fine for creating an instance of 'Candy' using the line: Candy *c = Factory::getCandy(CandyType::Normal)

I know my implementation may not be perfect, it is my first time trying to add Factory design to my code but it seems like it would be very useful in my program. Any pointers are greatly appreciated. Thank you in advance!

You say:

However I need the PowerUp candies to have some different methods than the superclass, so I do not know why I would store the return value of Factory::getCandy() in Candy* if I specifically want an instance of PowerUp* .

If this is true, the factory is meaningless, use a simple constructor. The whole point of a factory is to abstract away details (like the fact that your Candy really is, in fact, a PowerUp ) by sharing a common interface . In your case, if the application know the specific type it uses and call methods only this type has, it means there in no abstraction.

You could:

  1. Remove the factory and use a classic constructor.
  2. Review your Candy abstraction to make PowerUp a true implementation detail. In the end, in the eyes of the calling code , there should be no difference between using a PowerUp and any other Candy -like type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM