0

为了尝试替换单例模式和通用的“资源管理器”,我提出了一个解决方案。使资源静态和受保护。该资源在继承类的所有子级之间共享。它有效,但我不确定这是否是一个好方法。这里有一些代码来表达我在做什么(这里的资源是 sf::Texture):

class Foo {
public:
    Foo() {
        if(m_texture == nullptr) {
            //Création et chargement de la texture
            m_texture = std::unique_ptr<sf::Texture>(new sf::Texture());
            m_texture->loadFromFile("...");
        }

    }

    void draw(sf::RenderWindow& window) = 0;

protected:
    static std::unique_ptr<sf::Texture> m_texture = nullptr;

};

class Bar : public Foo {
public:
    Bar()
        : m_sprite(*m_texture) {}

    void draw(sf::RenderWindow& window) {
        window.draw(m_sprite); 
    }

private:
    sf::Sprite m_sprite;
};

这样我的资源就会被所有的孩子共享,并且只被初始化一次。替换我将通过引用随处携带的单例或资源管理器是否是一个好的解决方案。谢谢!

4

2 回答 2

1

从根本上说你要做的是正确的,一个静态成员将在所有继承的类之间共享(即完全相同),这样你只需要一个可以为你节省大量内存的实例,但这里有几个问题...我假设您使用的是 g++。

您不能在类声明中初始化非常量成员,所以这个。
static std::unique_ptr<sf::Texture> m_texture = nullptr;
会产生:
错误:ISO C++ 禁止非常量静态成员的类内初始化,
您必须在类的源文件中但在类之外对其进行初始化。 std::unique_ptr<sf::Texture> Foo::m_texture = nullptr;

其次,不保存直接访问成员字段,始终使用 setter 和 getter,即使在类函数中也是如此,这使得代码更易于维护。因此,您可以拥有一个名为 getTexture 的静态函数

static std::unique_ptr<sf::Texture> getTexture() {
    if(m_texture == nullptr) {
        //Création et chargement de la texture
        m_texture = std::unique_ptr<sf::Texture>(new sf::Texture());
        m_texture->loadFromFile("...");
    }
    return m_texture;
}

虽然 if 语句和函数调用确实会增加开销,但这更易于维护和更安全,并且它会在最后一分钟真正需要时加载纹理。

回到您的问题,Singleton 设计模式非常简单,主要用于节省内存,因为只创建了一个对象实例:) 资源管理器是一个完全不同的野兽,他们的目标是集中所有需要加载的操作和管理资源,将两者结合起来,您将初始化资源管理器的单个实例,然后通过静态成员字段访问它,让所有对象都请求资源,这可能是好是坏,具体取决于您要尝试的内容达到。

软件设计很难。我能给出的最好建议是,在设计系统时问自己这个问题,“我需要编写多少行代码才能引入另一个类似的组件”,你的目标应该是尽可能地减少这种情况,即尽可能多地重用尽可能你已经创建的。

最好的程序员是最懒惰的:) 不,我不是说复制/粘贴,应该禁止。

于 2012-06-10T02:55:56.327 回答
0

设计看起来很可疑。我看不出与更广泛使用的单例模式(使用函数本地静态实例)相比,使用它有任何优势。您可能最好在定义m_texture时使用默认值初始化对象Texture(而不是在Fooctor 中):

static std::unique_ptr<sf::Texture> m_texture( new sf::Texture() );

数据成员非常适合派生类。基类通常用于定义接口。

我建议您将资源管理器类 ( Foo) 分开,而不是从它继承,而是调用适当的成员函数来获取Texture对象。

于 2012-06-10T01:41:31.043 回答