Best way to implement abstract factory pattern

Consider the following code:

#include <stdio.h>


// =============================


class Shape{
public:
    virtual ~Shape(){};

    virtual void process() = 0;
};

class Triangle : public Shape{
public:
    virtual void process() override {
        printf("BBB\n");
    }
};


// =============================


/* option 1 */
class TriangleProducer{
public:
    Triangle factory(){
        return Triangle {};
    }
};



/* option 2 */
class PtrShapeProducer{
public:
    Shape *factory(){
        return new Triangle {};
    }
};



/* option 3 */
class PimplShape : public Shape{
    Shape *sh;
public:
    PimplShape(Shape *sh) : sh(sh){
    }

    virtual ~PimplShape() override{
        delete sh;
    }

    virtual void process() override {
        sh->process();
    }
};

class PimplShapeProducer{
public:

    PimplShape factory(){
        return new Triangle {};
    }
};


// =============================


int main(){
    TriangleProducer f1;
    Triangle tri = f1.factory();
    tri.process();



    PtrShapeProducer f2;
    Shape & sh = *f2.factory();
    sh.process();
    delete & sh;



    PtrShapeProducer f3;
    PimplShape psh = f3.factory();
    psh.process();



    return 0;
}

      

OPTION 1

That's nice, but it doesn't really provide polymorphism. The return type is known and you must match it. Can be added auto

instead Triangle

, but that doesn't change anything other than making refactoring easier.

OPTION 2

This is how Java and PHP do it. But I realized that "raw" pointers are not desirable in C ++. It can be added std::unique_ptr

, but again it doesn't change anything except for the missing operator delete

.

OPTION 3

This is what someone suggested here a while ago - works well, no "raw" pointers, no deletion. But this is so much code and too complicated - it seems fantastic, but not correct.

OPTION 4 (not implemented here)

Reproduction with const references - however they are constants and do not change the return type of the "factory". I think it looks more like a variation, it is not a real variation.

Any other option I'm missing?
And what's the best option?

+3


source to share


2 answers


I think the most idiomatic modern C ++ method is the one you mention along the way but ignore. Return a std::unique_ptr<Shape>

.

It's safe, clearly expresses ownership, supports polymorphism, and doesn't need a lot of code.

class ShapeFactory {
public:
  std::unique_ptr<Shape> create(){
    return std::make_unique<Triangle>();
  }
};

      



But I would not like to argue that this was the "best" method.

Yours PimplShape

in option 3 is actually quite similar to the unique_ptr

equally generic or proven one.

+6


source


Your factories run around the property. There is another alternative to this aspect; instead of going around the property, you can make the factory objects of your own:



   class Factory {
   public:
      ~Factory() { for(int i=0;i<vec.size();i++) delete vec[i]; }
      Shape &build_obj() {
         Shape *sh = new Triangle;
         vec.push_back(sh);
         return *sh;
       }

   private:
      void operator=(const Factory &);
      std::vector<Shape*> vec;
   };

      

0


source







All Articles