Как я могу создать фабрику? Клиент может устанавливать данные для методов, которые не определены в интерфейсе? (Проблема дизайна)

У меня небольшая проблема с дизайном: у меня есть одна фабрика, которая будет создавать объекты того или иного типа. Но мое клиентское требование состоит в том, чтобы предоставить (подавать) данные (через методы установки) из внешнего мира в конкретный класс типа 1, а не для типа 2.

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

e.g

     class ISubjectExecutor
     {
         public:
        virtual void ISUBJECTEXECUTOR_EXPORTS_API Execute()=0;  
     };

     class COMExecutor: public ISubjectExecutor
     {
      public: 
     virtual void Execute()=0;
            void setCLSID();
            void setGuids();

     };
     class Win32Executor : public IWin32Executor
     {
       public:               
      virtual void Execute()=0;
            void setFilePath();

     }; 

Теперь здесь я не могу использовать указатель ISubjectExecutor (*pSubjectExecutor) для вызова методов установки Win32Executor или COMExecutor по моему выбору в любое время после получения указателя (ISubjectExecutor) с завода. Потому что эти все сеттеры никогда не существуют внутри интерфейса ISubjectExecutor, и вы не можете получить доступ ни к одному методу, который никогда не содержался внутри интерфейса и существовал в конкретной реализации.

Как решить эту проблему дизайна, чтобы решить.?

С уважением Хасан


person Hassan    schedule 02.10.2010    source источник
comment
Если клиент уже знает, хочет ли он вызвать setCLSID()/setGuids() или setFilePath() для объекта, возвращенного фабрикой, то он уже знает конкретный тип объекта, поэтому он может просто преобразовать указатель в COMExecutor (если первый) или Win32Executor (если последнее). В этом случае на самом деле нет смысла использовать фабрику (или, по крайней мере, нет конструктивного преимущества).   -  person j_random_hacker    schedule 09.12.2010
comment
Мой комментарий выше применим, если вы хотите вызывать сеттеры для объекта, возвращаемого фабрикой. Лучшей схемой было бы передать фабрике различные параметры, чтобы объект, который она создает и возвращает вам, уже имел эти свойства.   -  person j_random_hacker    schedule 09.12.2010


Ответы (1)


Вы можете определить один или несколько чистых виртуальных методов в своем базовом классе, которые позволяют устанавливать свойство по тегу/значению (с соответствующими типами для значения и перечислением для тега). Затем производные классы реализуют код для подмножества значений тегов, которые они поддерживают, и, возможно, выдают какое-то исключение «не поддерживается» (или возвращают false?), если вызываются для обработки свойства, которое они не поддерживают. Здесь я использую std::string для представления значения, но вам может понадобиться другой тип или другие перегрузки.

 class ISubjectExecutor
 {
     public:
    virtual void ISUBJECTEXECUTOR_EXPORTS_API Execute()=0;  
    virtual void SetProperty(const Tag tag, const std::string& value) = 0;

   // full list of tags in all subclasses
   enum Tag {
     Guids,
     FilePath,
     CLSID
   };     
 };



 class COMExecutor: public ISubjectExecutor
 {
  public: 
    virtual void Execute()=0;

    // Valid tags are Guids, CLSID
    virtual void SetProperty(const Tag tag, const std::string& value);

 };
 class Win32Executor : public IWin32Executor
 {
   public:               
  virtual void Execute()=0;

    // Valid tags are FilePath
    virtual void SetProperty(const Tag tag, const std::string& value);
 }; 

Теперь можно вызывать SetProperty через указатель на ISubjectExecutor.

person Steve Townsend    schedule 03.10.2010