试图了解为什么单身人士被认为是一件坏事;为什么聚合更好?

时间:2013-01-13 02:27:45

标签: design-patterns singleton global

我试图理解为什么单身人士不满意。

假设我有单身MyClass:

class MyClass
{
public:
    void doSomething();
    static MyClass* getInstance();
private:
    int whatever;
    static MyClass* myClass;
    MyClass();
};

我有一个引用它的类:

void A::B()
{
    ...
    MyClass::getInstance()->doSomething();
}

我读到的是现在A类依赖于MyClass。测试类A有效地意味着同时测试MyClass。任何地方的任何人都可以同时修改我们的MyClass,因此A :: B()的结果是不可预测的。

但为什么全球可访问性是其原因?如果我们有聚合怎么办?如果A类有一个指针或对MyClass对象的引用,而其他类也有指向或引用同一个对象,该怎么办?

class A
{
public:
    void B();
private:
    MyClass* myClass;
};
void A::B()
{
    ...
    myClass->doSomething();
}

你能不能遇到同样的问题,其他一些类同时修改同一个myClass对象,因此A :: B()依赖于它?我想问题是,在多个地方引用相同的东西是不是几乎像“全球国家”?

(我知道此问题之前已经发布过,但我认为其他人没有具体询问为什么对同一个对象的多个引用更好。)

1 个答案:

答案 0 :(得分:1)

“任何地方的任何人都可以同时修改我们的MyClass”

这只能在某种多线程或多进程环境中实现。如果关注的话,你的第二个例子似乎并没有好转。

Globals - 或称为Singletons作为您的称呼 - 不建议在多线程环境中使用,因为可能是并发访问,这就是您所说的。为了避免并发问题,您需要处理同步机制 - 并不总是那么容易。

即使没有多线程,Globals也会使代码难以管理,调试和控制,而不仅仅是琐碎的系统。

通常,“聚合”不是“单身”的替代品。 singleton的替代方案是多个实例,每个实例专用于特定线程,或者是特定类或方法的本地实例 - 也许是“聚合”的意思 - 从而避免并发和控制/代码管理问题。

汇总“委托”“对象组合”(在此上下文中或多或少的同义词)通常被视为替代方案继承:而不是从基类继承功能,通常更需要设计一个完全独立的类来执行必要的功能,并由调用类引用和控制 - “黑盒子”概念

继承的问题之一是它倾向于强制派生类处理来自基类的实现和行为,这在派生类中可能是不合适的。它总是强制将实现细节暴露给派生类,从而违反封装。理想情况下,一个设计良好的类层次结构将避免这个问题,但如果你正在处理类Cat(动物),类Dog(Animal)等教科书定义之外的任何事情,设计这样的类层次结构通常不是一件简单的事。