views:

38

answers:

1

Hello,

I am having little design problem: I have one factory which will create object of with one type or another type. But my client requirement is to give(feed) the data(via setter methods) from outside world to the concrete class of type-1 not for type-2.

If I place these setter methods in interface, those need to be implemented forcefully both of concrete classes. This is NOT my requirement. I want to feed 1 kind of data for 1st type(some setters) and want to give another kind of data for other type(probably different setters other than which's contained by previous type.)

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();

     }; 

Now here I can't use pointer of ISubjectExecutor (*pSubjectExecutor) to call setter methods of Win32Executor or COMExecutor on my choice at any time after reciving pointer(ISubjectExecutor) from factory. Because those all setters never exist inside ISubjectExecutor interface, and you can't access any method which's never contained inside interface and exist in concrete implementation.

How to tackle this design problem to solve.?

Regards Hassan

A: 

You could define one or more pure virtual methods in your base class that allows a property to be set by tag/value (with appropriate types for value, and an enum for the tag). Then the derived classes implement code for the subset of tag values that they support, and maybe throw some kind of "not supported" exception (or return false?) if called to process a property that they do not support. Here I am using std::string to represent the value but you may need a different type, or other overloads.

 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);
 }; 

It's now legal to call SetProperty through a pointer to ISubjectExecutor.

Steve Townsend