我应该如何处理只应由工厂类使用的setter方法?

时间:2014-10-23 21:50:32

标签: c++ oop

我正在使用工厂类从内存池中生成许多小类。这些小类在工厂退回后是不变的。

目前,这些小对象之一的典型声明如下:

class LittleObject
{
public:
    ...//non-getter and setter member functions
    int getMemberVariable1() const;//should be accessible to everyone
    void setMemberVariable1(int newMemberVariable1Value);//should only be accessible to factory class
    ...//more getters and setters
private:
    ...
};

所以,你可以看到getter和setter都在公共区域。但是,应该设置值的唯一时间是在工厂类构建它的时间。现在,我可以清楚地看到一个选项,我将setter函数移动到私有访问,并使工厂成为LittleObject类的朋友。我发现这个选项有点不优雅,因为它将其他私有成员函数暴露给工厂。工厂无法访问的私人会员功能。

所以我的问题是:制作它的最佳方法是什么,只有工厂类才能使用setter函数?

5 个答案:

答案 0 :(得分:3)

我会使用friend class

class LittleObject
{
    friend class LittleObjectFactory;

public:
     int getMemberVariable();

private:
     void setMemberVariable( int value );
};

答案 1 :(得分:1)

我真的更喜欢friend工厂,但如果你需要更强的工作 封装,牺牲优雅,mabe可以做到

struct LittleData;

class Factory
{
public:
    void MakeLittle(LittleData&);
};

struct LittleData
{
    int data1;
    float data2;
};

class LittleObject
{
public:
    LittleObject(const LittleObject&) = default;
    LittleObject& operator=(const LittleObject&) = default;

    int GetData1() const { return data.data1; }
    float GetData2() const { return data.data2; }

    static LittleObject MakeOne( Factory& f )
    {
        LittleObject obj;
        f.MakeLittle(obj.data);
        return obj;
    }
private:
    LittleObject();
    LittleData data;
};


看看我刚写的内容......我真的更喜欢friend

答案 2 :(得分:1)

另一种可能性是 模具

我的意思是每个LittleObject的静态实例预设为所需的配置,以便工厂只需要复制。

可以通过复制构造函数创建副本,或者如果您不想制作其中一个(并且对象很简单),那么您可以使用memcpy()

以下是使用复制构造函数的示例:

class LittleObject1
{
    int a;
    int b;

public:
    LittleObject1(const LittleObject1& o): a(o.a), b(o.b) {}
    LittleObject1(int a = 0, int b = 0): a(a), b(b) {}

    static LittleObject1 stencil;

    int get_a() const { return a; }
    int get_b() const { return b; }
};

LittleObject1 LittleObject1::stencil(3, 7); // preset values

class LittleObject2
{
    std::string s;

public:
    LittleObject2(const LittleObject2& o): s(o.s) {}
    LittleObject2(const std::string& s = ""): s(s) {}

    static LittleObject2 stencil;

    std::string get_s() const { return s; }
};

LittleObject2 LittleObject2::stencil("hello"); // preset values

class Factory
{
public:

    template<typename Type>
    Type* create() const
    {
        return new Type(Type::stencil); // make a copy of the preset here
    }
};

int main()
{
    Factory fact;

    LittleObject1* o1 = fact.create<LittleObject1>();

    std::cout << o1->get_a() << '\n';
    std::cout << o1->get_b() << '\n';

    LittleObject2* o2 = fact.create<LittleObject2>();

    std::cout << o2->get_s() << '\n';
}

只有在预设值且不需要在运行时计算时,这才有用。

答案 3 :(得分:1)

依靠const-correctness

你说工厂返回的对象是不变的。 在这种情况下,为什么不只是返回const个对象:

class Factory
{
public: 
   std::unique_ptr<const DynamicLittleObject> createDynamicLittleObject();

   const AutomaticLittleObject createAutomaticLittleObject();

};

然后确保以const-correct方式编写其功能将提供正确的访问控制。

有些人可能会担心用户可能会抛弃常量,但是只有这么多值得做以保护他们自己。

答案 4 :(得分:0)

您可以使工厂成为每个对象的静态成员函数。所以每个对象类型都知道如何创建自己。然后你可以使用某种模板功能来减少创建它们。

有点像这样:

class LittleObject1
{
    int a = 0;
    int b = 0;

public:
    virtual ~LittleObject1() {}

    static LittleObject1* create()
    {
        LittleObject1* o = new LittleObject1;
        o->a = 1;
        o->b = 2;
        return o;
    }
};

class LittleObject2
{
    std::string s;

public:
    virtual ~LittleObject2() {}

    static LittleObject2* create()
    {
        LittleObject2* o = new LittleObject2;
        o->s = "hello";
        return o;
    }
};

template<typename Type>
Type* createType(Type*)
{
    return Type::create();
}

int main()
{
    LittleObject1* o1 = createType(o1);
    LittleObject2* o2 = createType(o2);
}