Какой шаблон использовать, чтобы отделить создание объекта от его класса - PullRequest
1 голос
/ 22 ноября 2011

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

Сначала я реализовал все переменные-члены, необходимые для создания Foo, отдельно в FooCreator и добавил функцию createFoo (), но в концеFooCreator стал почти копией Foo плюс еще несколько переменных состояния.

Далее я решил позволить FooCreator наследовать от Foo, что экономит много печатания, но это просто не похоже на чистое решение, так как для получения sth.Я должен сделать переменные-члены Foo защищенными, а не закрытыми, таким образом выставляя больше, чем я хочу для других пользователей.Foo не должен использоваться в качестве базового класса, кроме как для создания.

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

Пример кода может выглядеть следующим образом:

class Foo{
    private: //protected for second case
      int mVal;
      State mState;
      ComplexStuff mStuff;
      //...

    public:
      Foo():mVal(),mState(),mStuff(){}
      Foo(int val, State const& state, ComplexStuff const& stuff):
        mVal(val),mState(state),mStuff(stuff){}
      bool loadFromFile();

      bool evalStateTransition(State const& formerState) const{/*....*/}
      bool someTest(int) const{/*....*/};
      GraphicItem* visualize() const{/* ....*/};
      //...  
  };

  class FooCreator{  
    private:
      int mVal;
      State mState;
      ComplexStuff mStuff;

      StuffVisualizer mStuffVis;
      Paramset mParams;    
      //...

    public:
      FooCreator(Paramset const& set):
        mVal(),mState(),mStuff(),mStuffVis(),mParams(set){}
      constructState(int, int, int);
      gatherStuff1(File file1);
      Foo createFoo();

      int evalStateTransition(State const& formerState)  const{
        /*same long code as in Foo*/
      }
      bool someTest(int) const{ /*same long code as in Foo*/}
      GraphicItem* visualize() const{ /*same long code as in Foo*/}
      //...  
  };

  class FooCreator2 : public Foo{  
    private:
      StuffVisualizer mStuffVis;
      Paramset mParams;    
      //...

    public:
      FooCreator(Paramset const& set):Foo(),mParams(set){}
      constructState(int, int, int);
      gatherStuff1(File file1);
      Foo createFoo();    
  };

Ответы [ 2 ]

1 голос
/ 23 ноября 2011

просто напишите friend class FooCreator; в Foo, и теперь вы можете получить доступ ко всем приватным полям Foo из FooCreator. Затем просто создайте поле типа Foo в FooCreator ... Красиво и легко.

1 голос
/ 22 ноября 2011

Может быть хорошо не допускать сложной логики в конструктор .Однако, если вы не хотите использовать шаблон Factory или Builder , вы можете извлечь ParameterObject .

Если вам нужночтобы использовать методы в Foo для создания экземпляра, возможно, вам следует попытаться разделить Foo на два класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...