Эффективное создание большого количества небольших объектов C ++, которым необходим доступ к «глобальному» объекту - PullRequest
2 голосов
/ 07 февраля 2011

Вопрос о дизайне и эффективности c ++ ... Представьте себе этот код -

Database db;

class SmallObject
{
private:
    /* Some small amount of data and functions */
public:
    /* Constructor, more functions */
    void fn1() { /* Code that uses global db to do it's job */ }
    void fn2() { /* Code that uses global db to do it's job */ }
    void fn3() { /* Code that uses global db to do it's job */ }
    void fn4() { /* Code that uses global db to do it's job */ }
};

Это хорошо, эффективно и хорошо работает.Однако база данных является глобальным состоянием, что плохо.Это делает очень трудным тестирование класса в изоляции и т. Д. И означает, что SmallObject зависит от конкретной реализации базы данных.

Поэтому я реструктурирую его следующим образом: -

class SmallObject
{
private:
    /* Some small amount of data and functions */
public:
    SmallObject(Database& db) { db_ = db; }

    void fn1() { /* Code that uses global db_ to do it's job */ }
    void fn2() { /* Code that uses global db_ to do it's job */ }
    void fn3() { /* Code that uses global db_ to do it's job */ }
    void fn4() { /* Code that uses global db_ to do it's job */ }
};

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

class SmallObjectFactory
{
private:
    Database* db_;
public:
    SmallObjectFactory()
    {
        db_ = new SpecificDatabaseSubclass;
    }

    SmallObject* create() { return new SmallObject(db_); }
};

Это тоже работает, означает, что мой SmallObject больше не связан с точной реализацией базы данных, но все еще удобен в использовании.

Однако представьте, что существует 10000 экземпляров SmallObject.Теперь у каждого есть указатель на один и тот же объект базы данных.Это ужасно неэффективно, а также я не чувствую, что дублирование данных столько раз - это хороший дизайн ...

Итак, есть ли шаблон в C ++, который позволяет мне не делать базу данных глобальной, но позволяет мнене хранить повторяющиеся данные в каждом экземпляре SmallObject?

Это специально C ++, поэтому шаблоны и т. д. вполне подойдут ...

Ответы [ 5 ]

2 голосов
/ 07 февраля 2011

Шаблон называется FlyWeight, если я правильно помню.

Просто передайте базу данных в качестве аргумента каждому методу.

Это обменивает некоторую эффективность выполнения, удобство и гарантии на меньшее использование памяти.

Приветствия и hth.,

2 голосов
/ 07 февраля 2011

Вы можете определить статическое свойство db в классе SmallObject и назначить ему свою БД во время выполнения.Затем все экземпляры SmallObject могут использовать это свойство без необходимости иметь копии указателей на него.

2 голосов
/ 07 февраля 2011

Вы можете использовать Singleton Pattern , если используете уникальную базу данных.

1 голос
/ 07 февраля 2011

Если вы ищете эффективность, вполне возможно, что вы выделяете большое количество небольших объектов и хотите использовать какой-то пул.

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

Ваш конструктор должен выглядеть так:

   explicit SmallObject(Database& db) : db_(db) {}

Вы также должны правильно обрабатывать SmallObjectFactory, чтобы управлять временем жизни базового члена БД, что, вероятно, делает ваш класс не подлежащим копированию или использует shared_ptr.

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

1 голос
/ 07 февраля 2011

Вы говорите 10000 экземпляров, и все же в 32-битной системе это будет всего лишь 40 КБ памяти. Если вы не работаете во встроенном контексте, я бы предложил хранить указатель в каждом случае, как вы продемонстрировали во втором примере.

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

...