2

我试图理解为什么单身人士不受欢迎。

假设我有单身 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() 依赖于它吗?我想问题是,在多个位置引用同一事物不是几乎像“全球状态”吗?

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

4

1 回答 1

1

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

这仅在某种多线程或多进程环境中才有可能。如果这是问题的话,你的第二个例子似乎也好不到哪里去。

由于潜在的并发访问,不建议在多线程环境中使用全局变量(或您所称的单例变量),这就是您所说的。为避免并发问题,您将需要处理同步机制——并不总是那么容易。

即使没有多线程,Globals 也倾向于使代码难以在琐碎的系统中管理、调试和控制。

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

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

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

于 2013-01-13T02:54:18.523 回答