5

嘿。
在阅读了这里关于服务定位器模式的信息后,我开始思考只有静态成员的类是否真的是要走的路,或者普通的类 c 交互是否更合适。class我看到人们在他们甚至不需要它的时候一直在扔关键字。
从链接页面获取静态成员类的示例:

class Locator
{
public:
    static IAudio* GetAudio() { return service_; }

    static void Register(IAudio* service)
    {
        service_ = service;
    }

private:
    static IAudio* service_;
};

这也是一种方法:

// in .h
namespace Locator{
    IAudio* GetAudio();
    void Register(IAudio* service);
}

// in .cpp
namespace Locator{
    namespace {
        IAudio* service_;
    }

    IAudio* GetAudio() {
        return service_;
    }
    void Register(IAudio* service) {
        service_ = service;
    }
}

Locator::GetAudio()这两个示例都可以用和以完全相同的方式调用Locator::Register(...)。以上哪一项优于另一项?他们是一样的吗?有没有更好的方法来实现这一点?还是只是个人喜好?谢谢你的帮助。:)

4

2 回答 2

3

您的命名空间提案在可维护性方面略有不足 - 如果您出于某种原因需要更改接口,则必须记住同时更改接口 ( .h) 和实现 ( .cpp),否则可能直到链接时间才检测到不匹配。如果您使用 a class,那么编译器可以检测到诸如多个参数不匹配之类的错误。

另一方面,由于service_您的情况下的实现 ( ) 仅出现在.cpp文件中,因此您可以更改定位器的私有实现,而无需强制重新编译依赖于定位器的代码。(常见的基于类的模式可以提供同样的封装。)

这些都是相当小的差异。包含函数的公共命名空间几乎与只有静态成员函数的类完全相同。

于 2011-02-12T09:36:32.970 回答
0

使用类接口的一个很好的理由是一致性。

通常,在类中会有共享数据的支持实现或子类使用Locator。因此,最好(对许多人来说)在他们的代码库中使用一种方法,而不是为他们的静态数据组合命名空间和类(因为某些实现可能会扩展或专门化服务)。

许多人不喜欢处理静态数据。上述示例中的一些问题是:线程安全、所有权和数据的生命周期。如果将数据和实现限制在类范围(而不是文件范围),则可以更容易地维护这些数据和实现。这些问题随着程序复杂性的增加而增加——您发布的示例非常简单。

命名空间标签/别名更难传递(与类型/类型定义/模板参数相比)。如果您的接口相似并且您正在使用大量通用编程,或者您只是想实现测试,这将非常有用。

于 2011-02-12T10:11:34.827 回答