假设我有一个这样的课程:
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(); }
我还有全局对象。
即使MonkeyFishFactory本身在内部创建GlobalObjects
(所以它们现在在MonkeyFishFactory而不是真正的全局中),看起来像MonkeyFishFactory 本身仍然需要一个全局对象,以便我可以随时访问它,我想创建一个MonkeyFish
。
在这种情况下,工厂模式与全局状态不一样吗?
(我目前正在假设全球状态是坏事,并且消除它是一件好事。)
答案 0 :(得分:7)
你在这里混淆概念吗?
当您返回隐藏在抽象接口后面的具体类的实例时,通常会应用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
内容的用法或正确性是另一个问题。关于这个问题,可能还有一堆线程浮出水面。
答案 1 :(得分:6)
全球国家本身并不是坏事。 公开全球状态是一件坏事。 Factory模式有助于封装全局状态,这是一件好事。
答案 2 :(得分:5)
工厂没有全球状态。它只是创建对象。 既然它在工厂里没有任何状态。全球化是可以的。
答案 3 :(得分:3)
您不必离开全局对象。猴子鱼工厂应该按需创建GlobalOjectA | B | C.使用switch或if inside方法确定哪一个。
答案 4 :(得分:3)
您已对工厂中对象的创建进行封装控制。您希望隐藏您的实例化详细信息,而不是在需要新MonkeyFish的任何地方重现。考虑测试,单一责任和德米特定律。为什么你的班级想要使用MonkeyFish需要知道构建它的工作。如果你想测试MonkeyFish怎么办?如果你没有封装创建细节,你会怎么做?
答案 5 :(得分:3)
工厂类的工作是实例化一个对象并将其传递给调用者;不要选择要使用的全局实例化对象。因此,您的工厂示例不正确。它应该是:
int main()
{
MonkeyFish * monkey_fish = MonkeyFishFactory::buildMonkeyFish("Bob");
monkey_fish->go();
}
注意,没有全局对象,并且没有实例化MonkeyFishFactory。
答案 6 :(得分:1)
我认为您正在考虑Singleton模式,而不是工厂模式。在单例模式中,你只有一个类的实例,它基本上使它等同于一个全局对象,除了没有附加全局变量。
答案 7 :(得分:1)
如果你想得到一个好的答案,你应该陈述你的约束和要求。得到一个好答案最重要的是知道要问什么问题。
在您提供的代码段中,您决定使用全局变量,但这与您是否使用工厂无关。如果你使用仍然依赖于那些全局变量的工厂,那么你只需要另外一段代码来堆积其余部分。
尽量清楚说明你想要达到的目标,你可能会得到更好的答案。