правильный шаблон фабрики в C ++ - PullRequest
5 голосов
/ 28 января 2011

в C # вы должны объявить все в классе, чтобы пример фабричного шаблона мог выглядеть так:

namespace MySpace {

public class CFactory
{
  public static CFactory Current()
  {
    static CFactory singleton;
    return singleton;
  }
  public CBase Create() { return null; }
}

}

в C ++ у вас нет этого ограничения .. Так считается ли "плохой практикой", чтобы "фабричные" методы были глобальными функциями, а не были ли они классом?

пример 1:

namespace MySpace {

// factory method
std::shared_ptr<CBase> CreateBase() { return NULL; }

}

пример 2:

namespace MySpace {

// factory class
class CFactory
{
public:
  std::shared_ptr<CBase> CreateBase() { return NULL; }
};

// factory method exposing class
CFactory& GetFactory()
{
  static CFactory singleton;
  return singleton;
}

}

пример 3:

namespace MySpace {

// factory class with no global function
class CFactory
{
public:
  std::shared_ptr<CBase> CreateBase() { return NULL; }

public:
  static CFactory& getFactory()
  {
     static CFactory singleton;
     return singleton;
  }
};

}

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

Я использовал оба раньше, и я просто не уверен, считается ли один «лучше» по сравнению с другим

Ответы [ 4 ]

3 голосов
/ 28 января 2011

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

Ваш подход к фабрикации классов - это организационное изменение.Сама организация не является ни хорошей, ни плохой.Это может быть сделано хорошо или плохо.

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

1 голос
/ 29 января 2011

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

В стандартной библиотеке фабричные функции в основном существуют, потому что расширение шаблона функции может основываться на типах аргументов, но до C ++ 17 у вас не могло быть шаблонных классов, которые создают экземпляры класса на основе переданных типов. конструктору. Таким образом, эти фабричные функции более правильно рассматриваются как конструкторы, не являющиеся членами, чем фабрика. Например, они всегда возвращают экземпляр определенного типа.

В «истинной» фабрике фабрика может возвращать любой тип, который реализует указанный интерфейс или является производным от указанного типа. Истинные фабрики всегда возвращают указатели или (в редких случаях) ссылки, но не фактические экземпляры.

0 голосов
/ 29 января 2011

Свободные функции хороши в C ++, и я бы пошел по этому пути.

Несколько не связано: почему вы возвращаете общий умный указатель с фабрики?Всегда ли будет передано право собственности на вновь созданный объект?

0 голосов
/ 28 января 2011

Вот пример способа реализации синглтона в c ++
Таким образом, вы можете избежать глобального.
Надеюсь, это поможет.

 /* header file */

#ifndef EXAMPLE_H
#define EXAMPLE_H

class example
{
private:
    example(); // constructor
public:
    ~example(); // destructor
    static example *getExampleObject();
}
#endif

/* cpp file */
#include "example.h"

example *example::getExampleObject()
{
    static example *theInstance = NULL;
    if(theInstance == NULL)
    {
        theInstance = new example();
    }
    return theInstance;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...