实现抽象工厂模式的最佳方法

时间:2015-07-18 19:21:21

标签: c++ c++11 polymorphism

请考虑以下代码:

#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;
}

选项1

这很好,但它并没有真正实现多态性。返回类型已知,您必须匹配它。可以添加auto而不是Triangle,但除了更容易重构之外,这不会改变任何内容。

选项2

这就是Java和PHP的做法。但我明白了#34; raw&#34;指针在C ++中是不可取的。可以添加std::unique_ptr,但除了缺少delete语句之外,这不会改变任何内容。

选项3

这是有人在前一段时间提出的建议 - 效果很好,没有&#34;原始&#34;指针,没有删除。但它是如此多的代码,而且过于复杂 - 似乎很奇特,但不是正确的。

选项4 (此处未实施)

使用const引用 - 但它们是const并且它不会改变&#34; factory&#34;返回类型。我认为,这更像是变化,它不是真正的选择。

我缺少的其他选项?
还有什么是最好的选择?

2 个答案:

答案 0 :(得分:6)

我认为最常用的惯用的现代C ++方法是你提到但忽略的方法。返回std::unique_ptr<Shape>

它是安全的,明确表达所有权,支持多态并且不需要太多代码。

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

但我不想声称这是“最好的”方法。

选项3中的PimplShape实际上与unique_ptr非常相似,只是不太通用或经过测试。

答案 1 :(得分:0)

你的工厂正在绕过所有权。这方面还有另一种选择;而不是传递所有权,你可以使工厂拥有对象:

   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;
   };