Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Problem with design pattern decorator

Reply
Thread Tools

Problem with design pattern decorator

 
 
Gregory
Guest
Posts: n/a
 
      12-14-2006
I recently reviewed the decorator pattern in the GOF book and noticed a
problem.
Let look at the example given in the book. For simplicity I removed
intermediate Decorator class.

// Interface class
class VisualComponent
{
public:
VisualComponent();
virtual void Draw();
virtual void Resize();
// ...
};

// Concrete component
class TextView: public VisualComponent
{
public:
TextView(...);
virtual void Draw();
virtual void Resize();
// ...
private:
// ...
};

// Decorator
class BorderDecorator : public VisualComponent
{
public:
Decorator(VisualComponent*);
virtual void Draw();
virtual void Resize();
// ...
private:
void DrawBorder ( int ) ;
private:
VisualComponent* _component;
int _width;
};

void BorderDecorator :: Draw ()
{
_component->Draw ( ) ;
DrawBorder (_width) ;
}

void BorderDecorator: :Resize ()
{
_component->Resize ( ) ;
}

The BorderDecorator class stores pointer to the VisualComponent object
and delegates
execution of all its methods to the same method of this object. However
for the Draw() method
additional functionality (drawing window border) is added. Good so far.
But what happens if the concrete component TextView implements its
methods using
the decorated Draw() method. Lets say:

void TextView::Resize ()
{
// Do some resing stuff
.....
// Re-draw the window
Draw();
}

Then when invoking BorderDecorator::Resize() method no border will be
drawn for the
TextView window. This breaks our original intention to draw border
every time the TextView is
displayed.
In general it seems that decorator pattern does not behave well when
the decorated
public functionality (method Draw() above) is used in some Concrete
component methods (Resize()).

Does anybody know any solution to the described decorator problem ?

Gregory

 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      12-15-2006
Gregory wrote:
>
> I recently reviewed the decorator pattern in the GOF book and
> noticed a problem. Let look at the example given in the book. For
> simplicity I removed intermediate Decorator class.
>
> // Interface class
> class VisualComponent
> {
> public:
> VisualComponent();
> virtual void Draw();
> virtual void Resize();
> // ...
> };
>
> // Concrete component
> class TextView: public VisualComponent
> {
> public:
> TextView(...);
> virtual void Draw();
> virtual void Resize();
> // ...
> private:
> // ...
> };
>
> // Decorator
> class BorderDecorator : public VisualComponent
> {
> public:
> Decorator(VisualComponent*);
> virtual void Draw();
> virtual void Resize();
> // ...
> private:
> void DrawBorder ( int ) ;
> private:
> VisualComponent* _component;
> int _width;
> };
>
> void BorderDecorator :: Draw ()
> {
> _component->Draw ( ) ;
> DrawBorder (_width) ;
> }
>
> void BorderDecorator: :Resize ()
> {
> _component->Resize ( ) ;
> }
>
> The BorderDecorator class stores pointer to the VisualComponent
> object and delegates execution of all its methods to the same method
> of this object. However for the Draw() method additional
> functionality (drawing window border) is added. Good so far. But
> what happens if the concrete component TextView implements its
> methods using the decorated Draw() method. Lets say:
>
> void TextView::Resize ()
> {
> // Do some resing stuff
> .....
> // Re-draw the window
> Draw();
> }
>
> Then when invoking BorderDecorator::Resize() method no border will
> be drawn for the TextView window. This breaks our original intention
> to draw border every time the TextView is displayed. In general it
> seems that decorator pattern does not behave well when the decorated
> public functionality (method Draw() above) is used in some Concrete
> component methods (Resize()).
>
> Does anybody know any solution to the described decorator problem ?


The obvious solution would be something like this:

void TextView::resize( VisualComponent& parent )
{
// do resizing stuff
parent.Draw();
}

void BorderDecorator::resize()
{
_component->Resize( *this );
}

To implement such a solution, you either need to be able to modify the
classes in question, or the original designer would have to have
thought of the problem and created the appropriate passthrough
functions. A passthrough function would be needed whenever a concrete
class calls a member-function of the ABC.

Of course, the passthrough function will have to be part of the
VisualComponent interface, probably as a protected pure virtual
member-function.

 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      12-15-2006
Daniel T. wrote:
>
> The obvious solution would be something like this:
>
> void TextView::resize( VisualComponent& parent )
> {
> // do resizing stuff
> parent.Draw();
> }
>
> void BorderDecorator::resize()
> {
> _component->Resize( *this );
> }
>
> To implement such a solution, you either need to be able to modify the
> classes in question, or the original designer would have to have
> thought of the problem and created the appropriate passthrough
> functions. A passthrough function would be needed whenever a concrete
> class calls a member-function of the ABC.
>
> Of course, the passthrough function will have to be part of the
> VisualComponent interface, probably as a protected pure virtual
> member-function.


I forgot to mention... BorderDecorator will of course also need to
implement resize( VisualComponent&). That should be done like this:

void BorderDecorator::resize( VisualComponent& parent )
{
_component->resize( parent );
}

So the top-level decorator has its 'resize()' function called, the
interum decorators have their 'resize(VisualComponent&)' functions
called, the bottom-level object also has it's
'resize(VisualComponent&)' function called, in which it resizes and
calls parent.draw(). 'parent' will be the top-level object.

 
Reply With Quote
 
Gregory
Guest
Posts: n/a
 
      12-15-2006

"""Daniel T. ΠΙΣΑΜ(Α):
"""
> Daniel T. wrote:
> >
> > The obvious solution would be something like this:
> >
> > void TextView::resize( VisualComponent& parent )
> > {
> > // do resizing stuff
> > parent.Draw();
> > }
> >
> > void BorderDecorator::resize()
> > {
> > _component->Resize( *this );
> > }
> >
> > To implement such a solution, you either need to be able to modify the
> > classes in question, or the original designer would have to have
> > thought of the problem and created the appropriate passthrough
> > functions. A passthrough function would be needed whenever a concrete
> > class calls a member-function of the ABC.
> >
> > Of course, the passthrough function will have to be part of the
> > VisualComponent interface, probably as a protected pure virtual
> > member-function.

>
> I forgot to mention... BorderDecorator will of course also need to
> implement resize( VisualComponent&). That should be done like this:
>
> void BorderDecorator::resize( VisualComponent& parent )
> {
> _component->resize( parent );
> }
>
> So the top-level decorator has its 'resize()' function called, the
> interum decorators have their 'resize(VisualComponent&)' functions
> called, the bottom-level object also has it's
> 'resize(VisualComponent&)' function called, in which it resizes and
> calls parent.draw(). 'parent' will be the top-level object.


Thanks for your answer. Nice idea ! Let me see if I understand it
correctly. The TextView will finally recieve the top-level decorator
pointer in its Resize(VisualComponent& parent), so the parent is the
top-level decorator and then the Draw() method will be called correctly
whether it was decorated or not. Really elegant solution. Thanks a lot
!

Gregory

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ and design Pattern (Composite design Pattern ) Pallav singh C++ 1 01-22-2012 10:48 PM
C++ and design Pattern (Composite design Pattern ) Pallav singh C++ 0 01-22-2012 10:26 PM
C++ and design Pattern (Composite design Pattern ) Pallav singh C++ 0 01-22-2012 10:25 PM
May I have a example of design pattern of "composite", I still feel fuzzy after reading book of Addison-Wesley's"design pattern " jones9413@yahoo.com C++ 1 08-31-2007 04:09 AM
explanations about the Decorator design pattern Jean Lutrin Java 8 11-18-2004 05:40 PM



Advertisments