静态成员类与普通的c-like接口

时间:2011-02-12 09:29:08

标签: c++ design-patterns static-members service-locator

嘿那里。
在阅读了关于服务定位器模式的here后,它让我想到一个只有静态成员的类真的是要走的路,或者正常的类似c的interace是不合适的。我发现人们甚至不需要它时会一直围绕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(...)可以完全相同地调用这两个示例。 上面的一个优于其他?它们是一样的吗?有没有更好的方法来实现这一目标?或者仅仅是个人偏好?谢谢你的帮助。 :)

2 个答案:

答案 0 :(得分:3)

您使用命名空间的提议在可维护性方面略有弱点 - 如果由于某种原因需要更改界面,则必须记住更改界面(.h)和实现(.cpp) ,或链接时间之前可能无法检测到不匹配。如果您使用class,则编译器可以检测到错误,例如许多参数不匹配。

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

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

答案 1 :(得分:0)

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

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

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

命名空间标签/别名更难以传递(与types / typedef / template参数相比)。如果您的接口相似并且使用了大量的泛型编程,或者您只是想实现测试,那么这很有用。