2012-06-10 2 views
0

В попытке заменить одноэлементный шаблон и общий «диспетчер ресурсов» я пришел с решением. Создание ресурса статическим и защищенным. Этот ресурс разделяется между всеми дочерними элементами унаследованного класса. Это работает, но я не был уверен, что это хороший способ. Вот немного кода, чтобы выразить то, что я делаю (ресурс здесь КФ :: 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; 
}; 

Таким образом, мои ресурсы является общим на всех детей, и только инициализируется один раз. Является ли это хорошим решением для замены синглтона или диспетчера ресурсов, которые я буду носить повсюду посредством ссылки. Спасибо!

+0

Мне нравится сама идея, и я был в Google, чтобы узнать, есть ли у меня подозрение в производительности. Каждый раз, когда я вижу шаблон, я вижу стоимость косвенности. Кажется, это способ очистить вонь от одиночек.
Это помещает метаданные класса туда, где они принадлежат, внутри класса. Я хотел бы пойти дальше и сказать, что если вы ищете производительность и гибкость создания объектов, это хороший дизайн, чтобы сделать это с другими шаблонами, добавив альтернативные фабрики в качестве статических функций, чтобы поддерживать другие шаблоны с разными интерфейсами.
Какие преимущества получают через экстернализацию? –

ответ

1

Принципиально то, что вы связываете, правильно, статический член будет разделяться (т.е. быть точно таким же) среди всех унаследованных классов, таким образом вам нужен только один экземпляр, который может сэкономить массу памяти, но heres пара вопросов ... Я предполагаю, что вы используете g ++.

Вы не можете инициализировать элемент non-const в объявлении класса, так что это.
static std::unique_ptr<sf::Texture> m_texture = nullptr;
будет производить это:
ошибка: ISO C++ запрещает в классе инициализации неконстантного статического члена
вы должны инициализировать его в исходном файле вашего класса, но вне класса. std::unique_ptr<sf::Texture> Foo::m_texture = nullptr;

Во-вторых, он не сохраняет для доступа к полям членов напрямую, всегда использует сеттеры и геттеры, даже в пределах функций класса, что делает код более удобным для обслуживания. Таким образом, вы можете иметь статическую функцию 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; 
} 

в то время как его правда, что если заявление и вызов функции действительно добавить приходят накладные расходы, это гораздо легче поддерживать и безопаснее, и загрузить текстуру в последнюю минуту, когда это действительно необходимо.

К вопросу о шаблоне проектирования Singleton довольно просто и в основном используется для сохранения памяти, поскольку только один экземпляр объекта когда-либо создан :) Руководители ресурсов - это совершенно другой зверь, цель которого - централизовать все действия которые требуются для загрузки и управления ресурсами, объединяя два варианта, вы должны инициализировать один экземпляр диспетчера ресурсов, а затем обращаться к нему, хотя статическое поле-член, имея все объекты, запрашивающие ресурсы, это может быть хорошим или плохим, в зависимости от того, что вы пытаетесь достичь.

Разработка программного обеспечения сложная.Лучший совет, который я могу дать, заключается в следующем: при проектировании системы спросите себя: «Сколько строк кода я должен написать, чтобы ввести другой подобный компонент», ваша цель должна заключаться в том, чтобы максимально минимизировать это, то есть повторное использование насколько возможно то, что вы уже создали.

Лучшие программисты самые ленивые :) и нет, я не имею в виду копирование/вставку, которые должны быть запрещены.

+1

Для вашего первого момента, я знаю об этом, и я использую VS2010. Это было упрощено, но я инициализирую указатель, как вы делаете на улице. Для вашего второго пункта, имеет смысл, спасибо. В-третьих, я не хотел делать синглтон, так как он довольно глобальный, и мне это не нравятся. Окончательно, я делаю все это, чтобы узнать и получить хорошее представление, чтобы я мог поправляться. В этом контексте я хотел изучить другую альтернативу singleton и менеджеру ресурсов. Кроме того, я ненавижу Copy/paste, поскольку я ничего не узнаю. – Rosme

+0

СПАСИБО! Я хочу, чтобы больше программистов подумали, как вы! Шаблон проектирования singleton одобрен, если у вас есть небольшое количество объектов, но становится очень сложно управлять им, когда количество объектов увеличивается, поэтому он редко используется сам по себе, много раз мы занимаем идеи от разных проектов до внедряйте наши системы ... Если вы всегда получаете доступ к своим членам через сеттеры/геттеры, это нормально даже в глобальном масштабе :) –

+0

также смотрите на сцепление и сцепление. –

0

Дизайн выглядит подозрительно. Я не вижу никакого преимущества использования этого по более широко используемому шаблону Singleton (с помощью локального статического экземпляра функции). Вы, вероятно, лучше с инициализацией m_texture объекта со значением по умолчанию Texture в точке определения (а не в CTOR Foo «s):

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

члены данных идеально подходят для производных классов. Базовые классы обычно определяют интерфейсы.

Я предлагаю вам разделить класс менеджера ресурсов (Foo) и вместо этого наследовать от него, вызвать соответствующие функции-члены, чтобы добраться до объекта Texture.

+0

Тот факт, что он является статичным, позволяет получить только одну инициализацию объекта, и только в том случае, когда это значение равно nullptr. Он работает, вы можете попытаться поставить 'std :: cout <<" Init ";' внутри оператора if, и он появится только один раз, даже при создании двух объектов 'Bar'. – Rosme

+1

Ах. Да. Виноват. Я пропустил тест 'if'. Во всяком случае, это все еще не похоже на хороший способ реализации. Элементы данных идеально подходят для производных классов. Базовые классы обычно определяют интерфейсы. Я предлагаю вам взглянуть на идиому handle-body/pimpl. – dirkgently

+0

Именно поэтому я и спросил. Он работает хорошо, но я действительно не был уверен в этом. Иду взглянуть на идиому. Спасибо. – Rosme

Смежные вопросы