From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Decorator pattern : Changing parameters of concrete decorators

I am exploring the decorator pattern at the moment.

 

I include an example.

 

Base Class defines a method "Do Something".

Decorator abstract class accepts either a DVR of a base class or a base class object directly.  When overriding "Do Something" if the DVR Reference is valid, it calls "Do Something" on the DVR, otherwise it calls "Do Something" on the object.  I include both versions just to show that the actual storage of the item to decorate is possible either way.

I then define two decorators, a counter (counts how often "Do Something" is called) and "Max" which records the maximum value sent to "Do Something".  Both decorators publish their results in a notifier encapsulated within them.

 

This works well and I think it more or less adheres to the idea of the decorator pattern.

 

Questions arise when I need, at run-time, access to the data fields of the decorators themselves (I include step size for the counter, but resetting the maximum would also be a good example).  When using cascaded decorators, storing the one I require access to as a DVR in any subsequent decorator allows me to retain direct access to the inner data and control it.  Is there another way of doing this?  Command pattern and chain of responsibility seems a bit O.T.T. to behonest.

 

0 Kudos
Message 1 of 9
(3,479 Views)

Hi Intaris,

 

I understood, what you are doing, but I do not understand, what is your question.

 

I think an example scenario could be helpful. Which class contains the data you want do get or manipulate and with which class or object do you work in that case?

 

Best regards,

Melanie

Best regards,
Melanie Eisfeld
Senior Applications Engineer, National Instruments Germany
Certified LabVIEW Developer
Certified TestStand Architect
0 Kudos
Message 2 of 9
(3,421 Views)

The example contains two different ways of adding layers of decorators.

 

Because adding functionality in this way is not done via inheritance, the top-most (the last decorator defined) actually doesn't know what types of decorators are contained within.  In my case it's Max -> Count -> Base but it could just as easily be Cound -> Max -> Count -> Base.

 

Since the containing object does not actually know what it is containing, how do we keep any kind of ability to modify the "middlemen" in the final decorator.  Obviously, the "Max" decorator does not support the "Count" decorator interface (since that would require inheritance) so I'm assuming we need to retain a way to keep "direct" access to the "middleman".  We retain the first and last object methods, but not the ones in between.

 

So if I have a Base class which does -something- (what it does is unimportant at the moment because at this level I can make the decorator support the methods of the "Base" object.).  I wrap this in a decorator (Count)  So now I have Count -> Base.  Currently I can access both "Base" and "Count" methods.  No problems yet.  If I add another level of decorator, Max, then I now have Have Max -> Count -> Base.  The object on my wire is now of type "Max" and I have access to the "Max" and "Base" methods.  If I need access to the "Count" methods, how to achieve this?

 

In my example I have stored a DVR of the "Count" object before encapsulating it in the "Max" decorator.  I'm not sure this is the best way.

0 Kudos
Message 3 of 9
(3,402 Views)

Base Class

+Do Something()

 

Decorator (Inherits from same class as Base Class)

-Base Class

+Add Base Class()

+Do Something() -> Base Class.Do Something()

 

Count (Inherits from Decorator)

+Set Step Size()

+Do Something() -> Parent.Base Class.SDo Something()

 

Max (Inherits from Decorator)

+Reset Count()

+Do Something() -> Parent.Base Class.SDo Something()

 

If an Object of Type Max holds an object of Type Count which in turn holds an Object of Type Base, How to call the function Count.Set Step Size()?

Similarly, if an Object of Type Count holds an Object of type Max which in turn holds an Object of type Base, how to call Reset Count()?

0 Kudos
Message 4 of 9
(3,388 Views)

I'm afraid I don't have an answer, and only use "Decorator" pattern in "configure-and-forget" things.   These are not uncommon, though, as one often wants to inject a configured object into code that only deals with a parent class (and so knows nothing about any of your decorators anyway).  You can use references of some kind to maintain a connection to the decorator.  

 

My most commonly used decorator code is the "Observer" class in Messenger Library.  It, by design, never lets one access the original objects inside it, but as the objects it contains are mainly reference-based, one can retain a separate copy of them and act on them remotely.

Message 5 of 9
(3,382 Views)

I'm left with the feeling that such an operation, i.e. not a "Fire and forget" decorator is a bit against the idea.  But in the GOF design patterns book, on Page 176 it is written "For example, ScrollDecorator's ScrollTo operation lets other objects scroll the interface if they know there happens to be a ScrollDecorator object in the interface"

 

Could it be they are simply referring to the top-most decorator (i.e. the decorator object we ACTUALLY communicate with)?

 

Do you reckon retaining a reference and working with that is OK?  Not any major anti-pattern?  I won't have the OOP police at my door any time soon?

0 Kudos
Message 6 of 9
(3,355 Views)

Not being a OOPer type...

 

I think you would have to have a method in the Base to be able to get at those things.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 7 of 9
(3,321 Views)

Being one that tries in the background to apply new ideas, I was thinking about a situation where I could use the Decorator pattern.

 

It seems to be usefull for situations where the methods apply to some thing ahd is self contained.

 

Q:

 

Video game where we have the choice of what type of facial hair a character has?

 

The Base class has a method "render face".

 

Children can be goatee, mustache, side burns, Duck Dynasty.

 

The method "render face" in teh base class just returns an image with no facial hair. The Docorators add their part to the bare face.

 

Trying,

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 8 of 9
(3,287 Views)

Personally, having dabbled in this fo rthe first time recently I find the name "Decorator" to be rather misleading suggesting UI aspects which really don't have to be.

 

I prefer one of the alternate names which is "Wrapper".

 

Say I have an object which takes a DBL Value.  Whenever we enter a new value it will trigger an event.  Now I want it to only trigger an event when the value changes.  I can wrap the original object in a new object, implement the same method "Set Value" but only actually call the original method's Set Value VI if it has changed versus the last value.

 

A similar option would be sending the value to a Queue for logging.

 

With Inheritance you need to statically combine these so that if you have (Logging inherits from Changed inherits from Base) then every time you want logging, you automatically also have the value changed functionality.  But maybe you don't want that.  Maybe I only want logging but no Value Changed functionality.  By having the "parent" class as a data member instead of a "real" parent you can mix and match the functionalities (and even change their orders) as you please.

 

Also Decoration does NOT use inheritance between the different levels of functionality so terms like "child" are misleading here.  They are "Impersonating as" relationships, somewhere between "has a" and "is a".  For me at least kind of half-way between composition and inheritance.

Message 9 of 9
(3,275 Views)