假设我有一个这样的课程:

class MonkeyFish
{
   MonkeyFish( GlobalObjectA & a, GlobalObjectB & b, GlobalObjectC & c);

   private:
     GlobalObjectA & m_a;
     GlobalObjectB & m_b;
     GlobalObjectC & m_c;
}

没有工厂,我需要执行以下操作才能实例化 MonkeyFish

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFish * monkey_fish = new MonkeyFish(a, b, c);
  monkey_fish->go();
}

另一方面,如果我有一个 MonkeyFishFactory ,似乎我必须这样做:

GlobalObjectA a;
GlobalObjectB b;
GlobalObjectC c;

int main()
{
  MonkeyFishFactory mf_factory(a, b, c);
  MonkeyFish * monkey_fish = mf_factory.buildMonkeyFish("Bob");
  monkey_fish->go();
}
  1. 我还有全局对象。

  2. 即使MonkeyFishFactory本身在内部创建 GlobalObjects (所以它们现在在MonkeyFishFactory而不是真正的全局中),看起来像MonkeyFishFactory 本身需要是一个全局对象,以便我可以随时访问它,我想创建一个 MonkeyFish

  3. 在这种情况下,工厂模式与全局状态不一样吗?

    (我目前正在假设全球状态是坏事,并且消除它是一件好事。)

有帮助吗?

解决方案

你在这里混淆概念吗?

当您返回隐藏在抽象接口后面的具体类的实例时,通常会应用Factory模式。这个想法是调用者只看到界面,甚至不知道对象的具体类型是什么。所有这些都是基于参数创建一个对象实例,并将与决定从创建对象的用户创建的对象相关联的逻辑解耦。

您所描述的是Singleton(或MonoState)和Factory的混合体。你的工厂有状态所以不能静止。在这种情况下,您需要应用类似Singleton模式的东西来控制单个Factory实例的创建,并在其中隐藏适当的全局变量:

class IMonkeyFish {
public:
    virtual ~IMonkeyFish() = 0;
    virtual void go() = 0;
};

class Factory {
public:
    static Factory& instance();
    IMonkeyFish* createMonkeyFish();
protected:
    Factory(GlobalObjectA& a, GlobalObjectB& b, GlobalObjectC& c);
private:
    static Factory *theInstance;
    GlobalObjectA&  instanceOfA;
    GlobalObjectB&  instanceOfB;
    GlobalObjectC&  instanceOfC;
};

Factory& factory = Factory::instance();
IMonkeyFish* fishie = factory.createMonkeyFish();
fishie->go();

Singleton 模式控制工厂实例的创建。 Factory 模式隐藏了创建实现 IMonkeyFish 接口的对象的细节。 Good Thing(TM)隐藏了全局状态,并将 MonkeyFish 具体细节与创建实例脱钩。

使用 Singleton 的用法或正确性是另一个问题。关于这个问题,可能还有一堆线程浮出水面。

其他提示

全球国家本身并不是坏事。 公开全球状态是一件坏事。 Factory模式有助于封装全局状态,这是一件好事。

工厂没有全球状态。它只是创建对象。 既然它在工厂里没有任何状态。全球化是可以的。

您不必离开全局对象。猴子鱼工厂应该按需创建GlobalOjectA | B | C.使用switch或if inside方法确定哪一个。

您已对工厂中对象的创建进行封装控制。您希望隐藏您的实例化详细信息,而不是在需要新MonkeyFish的任何地方重现。考虑测试,单一责任和德米特定律。为什么你的班级想要使用MonkeyFish需要知道构建它的工作。如果你想测试MonkeyFish怎么办?如果你没有封装创建细节,你会怎么做?

工厂类的工作是实例化一个对象并将其传递给调用者;不要选择要使用的全局实例化对象。因此,您的工厂示例不正确。它应该是:

int main()
{
  MonkeyFish * monkey_fish = MonkeyFishFactory::buildMonkeyFish("Bob");
  monkey_fish->go();
}

注意,没有全局对象,并且没有实例化MonkeyFishFactory。

我认为您正在考虑Singleton模式,而不是工厂模式。在单例模式中,你只有一个类的实例,它基本上使它等同于一个全局对象,除了没有附加全局变量。

如果你想得到一个好的答案,你应该陈述你的约束和要求。得到一个好答案最重要的是知道要问什么问题。

在您提供的代码段中,您决定使用全局变量,但这与您是否使用工厂无关。如果你使用仍然依赖于那些全局变量的工厂,那么你只需要另外一段代码来堆积其余部分。

尽量清楚说明你想要达到的目标,你可能会得到更好的答案。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top