Thread: Decorator

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248

    Decorator

    Hi,

    To clean up a class which contains too many fonctions and attributes, I want to implement decorators for that class.
    However, the class contains many virtual functions.

    If I understood well, I should re-implement all these virtual functions as (suppose I do not derive further from my decorator) :

    Code:
    class to_be_decorated {
     public:
      virtual bool foo();
    };
    
    class decorator : public to_be_decorated {
     public:
      decorator(class to_be_decorated&);
      bool foo() { return obj.foo(); }
     private:
      to_be_decorated& obj;
    };
    Am I right ?

    This will cause my simple decorators to become quite cumbersome as well... any other solutions or ideas?

    Thanks!!

    Mark
    Last edited by MarkZWEERS; 08-03-2009 at 10:01 AM.

  2. #2
    Unregistered User Yarin's Avatar
    Join Date
    Jul 2007
    Posts
    2,158
    >> If I understood well, I should re-implement all these virtual functions
    Nope, you can define function in your root class. Redefining it in the decorator is only necessary if it would differ from it's immediate parent.

  3. #3
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    The decorator pattern is not for "clean up a class which contains too many fonctions and attributes". It sounds like you are forcing a design pattern to do something for which it was not intended.

    To me, it sounds like you just need to break out your monolithic class into several different classes. Take a look at your class, and ask yourself, "what functions does this class perform"?. Then maybe see if you can break those functions out to separate classes.

    The decorator pattern is to add functionality to a class at runtime, but it doesn't sound like this is what you need.
    bit∙hub [bit-huhb] n. A source and destination for information.

  4. #4
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Nope, you can define function in your root class. Redefining it in the decorator is only necessary if it would differ from it's immediate parent.
    But the decorator is a wrapper of an object ? If I don't re-define the virtual functions in that wrapper, I can not use the wrap-object instead of the wrapped object. That's what I want : add some data and/or functions at runtime to an existing object, then only use that extended object.

    So yes, it is to add data/functions at run-time, but I want to do it in a way that it doesn't impact existing functions which use the to-be-extended object.

    Thanks for your posts!

  5. #5
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    This what I've found in the GoF "Design Patterns" :

    The decorator conforms to the interface of the component it decorates so that its presence is transparant to the components clients. The decorator forwards requests to the component ...
    So basically after having decorated my component, I want my component itself to become the decorated version.

    Code:
    class Component {
     public:
      Component() {}
    };
    
    class Decorator : public Component {
     public:
      Decorator(Component const& p_comp) : _comp(p_comp) {}
     protected:
      Component _comp;
    };
    
    class BooDecorator_one : public Decorator {
     public:
      BooDecorator(Component const& p_comp) : Decorator(p_comp) {}
      void boo() { ... }
    };
    I do not want to modify all existing functions which take an object of "Component" as argument, so I would like to do something like this :
    Code:
    int main()
    {
      Component myComponent;
    
      BooDecorator myDecoratedComponent(myComponent);
    
      myComponent.boo();
    
      return 0;
    }
    which will of course fail since "boo()" is not a function of "Component" . But isn't this what the GoF ment by the citation?

    Something like
    Code:
      myComponent = myDecoratedComponent;
    seems odd to me.


    Has anyone an idea or solution for what I want? Thanks a lot !!

    Mark

  6. #6
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    You are not following the design pattern correctly. Your Component class needs to have an interface which is implemented by the decorator and your components.

    This would be a better example:
    Code:
    class Component {
    public:
        virtual void boo() = 0;  
    };
    
    class MyComponent {
    public:
        virtual void boo() { /* do something */ }
    };
    
    class Decorator : public Component {
    public:
        Decorator(Component* p_comp) : _comp(p_comp) {}
     protected:
        Component* _comp;
    };
    
    class BooDecorator_one : public Decorator {
     public:
        BooDecorator(Component const& p_comp) : Decorator(p_comp) {}
        void boo() { 
            _comp->boo();
            something_else();  
        }
    };
    
    int main()
    {
      Component myComponent;
    
      BooDecorator myDecoratedComponent(&myComponent);
    
      myComponent.boo();
    
      return 0;
    }
    Notice how Component now has an interface that is implemented by the decorators and the components. Also note that it would be much better for the decorator class to take a shared_ptr to a Component instead of just a raw pointer like in my example.
    bit∙hub [bit-huhb] n. A source and destination for information.

  7. #7
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    Hi,

    Your Component class needs to have an interface
    That's exactly my problem : the actual class hasn't got a proper interface.

    In the file tmp.png I've included the UML diagram :

    - "Component", "Composite", "DerivedComposite" are existing, non-abstract classes
    - "Decorator" and "BooDecorator" are to extend the functionality of "DerivedComposite".

    I guess a big problem will be the 'private' data in the class "DerivedComposite" ?

  8. #8
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Well without knowing more about your class structures, it's tough to help out further. The decorator design pattern requires a base class with an interface though, so if you don't have that, then you are going in the wrong direction.
    bit∙hub [bit-huhb] n. A source and destination for information.

  9. #9
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248
    OK thanks, then I'll try to solve that one first :-)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Visitor / Decorator Pattern
    By MarkZWEERS in forum C++ Programming
    Replies: 9
    Last Post: 05-16-2009, 11:53 AM
  2. Composite vs Decorator pattern?
    By cpjust in forum Tech Board
    Replies: 1
    Last Post: 04-22-2009, 11:33 AM
  3. Decorator Help
    By King Mir in forum C++ Programming
    Replies: 7
    Last Post: 06-14-2006, 12:18 PM