| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| Hi NG, I was reading an article about design patterns on codeproject that I actually liked pretty much. Until I got to part IV on the following page. http://www.codeproject.com/useritems...gpatterns2.asp I'm not that into these design patterns, but I think he explains the Decorator Pattern incorrectly. If I understand correctly, a decorator should add additional functionality to an object, but the caller doesn't need to know about the fact the the object on which it invokes a method is in fact a decorator. That implies that it isn't very useful to have the decorator add a new method, since it would never be invoked. Am I correct on this? I was starting to doubt since the comments at the end of the article are pretty positive. BTW I based my knowledge of the Decorator Pattern on the following site. http://www.dofactory.com/Patterns/PatternDecorator.aspx Which one is right? Thanks, Mark |
|
#2
| |||
| |||
| In article <45366641$0$724$5fc3050{}dreader2.news.tiscali.nl> , Capstar <news{}eg.homeip.net> wrote: > Hi NG, > > I was reading an article about design patterns on codeproject that I > actually liked pretty much. Until I got to part IV on the following page. > > http://www.codeproject.com/useritems...gpatterns2.asp > > I'm not that into these design patterns, but I think he explains the > Decorator Pattern incorrectly. If I understand correctly, a decorator > should add additional functionality to an object, but the caller doesn't > need to know about the fact the the object on which it invokes a method > is in fact a decorator. That implies that it isn't very useful to have > the decorator add a new method, since it would never be invoked. If new methods are being added, then it is more an adaptor than a decorator. You are right IMHO. -- There are two things that simply cannot be doubted, logic and perception. Doubt those, and you no longer*have anyone to discuss your doubts with, nor any ability to discuss them. |
|
#3
| |||
| |||
| Capstar wrote: > Hi NG, > > I was reading an article about design patterns on codeproject that I > actually liked pretty much. Until I got to part IV on the following page. > > http://www.codeproject.com/useritems...gpatterns2.asp > > I'm not that into these design patterns, but I think he explains the > Decorator Pattern incorrectly. If I understand correctly, a decorator > should add additional functionality to an object, but the caller doesn't > need to know about the fact the the object on which it invokes a method > is in fact a decorator. That implies that it isn't very useful to have > the decorator add a new method, since it would never be invoked. > > Am I correct on this? I was starting to doubt since the comments at the > end of the article are pretty positive. > BTW I based my knowledge of the Decorator Pattern on the following site. > > http://www.dofactory.com/Patterns/PatternDecorator.aspx > > Which one is right? The question to ask yourself is if the task at hand indeed warrants 5 extra classes (as on the diagramm you referred to). This whole pattern venture starts looking like a caricature to me. Do you really want to imitate all those messy human artifacts in your program? What is next, the "interior designer" pattern (in a code generation project)? "Real estate agent" (responsible for persistence)? |
|
#4
| |||
| |||
| Capstar wrote: > If I understand correctly, a decorator should add additional functionality > to an object, but the caller doesn't need to know about the fact the the > object on which it invokes a method is in fact a decorator. > That implies that it isn't very useful to have the decorator add a new > method, since it would never be invoked. If methods are added, callers that need the new functionality will need to know that they're using a particular decorator so that they can call the added method(s), but callers that don't need the new method(s) don't need to know that they're dealing with a decorator. If the Decorator merely changes the implementation of existing methods, then only the code that actually creates the Decorator needs to know about it. The Decorator pattern is simply the object-based analog of inheritance (which is a class-based technique). Anything that you can do with inheritance you can do with a Decorator (albeit with more effort). With inheritance the changes wrought by the subclass are locked in to every object of that subtype, but with Decorator only the decorated objects are changed. In addition, the changes can be added and/or removed at runtime if desired. Furthermore, each caller can have a different view of the same object depending on which decorator (if any) it is viewing the object through. As with inheritance, you can override methods and you can add methods. Of course, you can also use the original unchanged implementation of methods. By the way, the class called "Decorator" in those diagrams is not fundamental to the pattern; it's a convenience class for providing the default forwarding of the "Component" method call(s) to reduce code duplication when multiple concrete decorator classes exist. There is also no need to have multiple concrete decorator classes. The pattern is quite usable with the single interface called "Component" in the diagram, the concrete component class, and a single concrete decorator that does its own forwarding of method calls. |
|
#5
| |||
| |||
| Capstar wrote: > Hi NG, > > I was reading an article about design patterns on codeproject that I > actually liked pretty much. Until I got to part IV on the following page. > > http://www.codeproject.com/useritems...gpatterns2.asp > > I'm not that into these design patterns, but I think he explains the > Decorator Pattern incorrectly. If I understand correctly, a decorator > should add additional functionality to an object, but the caller doesn't > need to know about the fact the the object on which it invokes a method > is in fact a decorator. That implies that it isn't very useful to have > the decorator add a new method, since it would never be invoked. > > Am I correct on this? I was starting to doubt since the comments at the > end of the article are pretty positive. > BTW I based my knowledge of the Decorator Pattern on the following site. > > http://www.dofactory.com/Patterns/PatternDecorator.aspx > > Which one is right? > > Thanks, > Mark The author uses additional function, so that he can give the player to the decorator. This would be better done via constructor which is the approach in the GoF example. So the class would look like: public class PlayerRole { public PlayerRole(Player player) { _player = player; } } Notice however, that this is also adding of a new method - the constructor of the Decorator class which receives base class interface as its argument. At the same time, the default constructor is hidden (which is good - you explicitly forbid creation of a role without a player). Basically, you must have at least some specialization in the place where you create specific decorator. I see at least two reasons: a) you must wire the decorator with the role b) you might want to give the specific decorator some additional information, interesting only to that decorator So while I consider the code on the codeproject somewhat sloppy, I think the principle is demonstrated correctly. Sasa |
|
#6
| |||
| |||
| I felt that I should expound on a detail from my earlier posting: Doug Pardee wrote: > each caller can have a different view of the same object depending on > which decorator (if any) it is viewing the object through. Implied (rather obliquely) in this statement is that it is possible for one object to have multiple decorators at one time. I know of three programming methods that have formalized the use of object inheritance, and I think that there are some interesting perspectives to found. In Streamlined Modeling: - object inheritance is used in three different ways for modeling business domain data - an object can have multiple simultaneous children - each child can have only one parent at a time (single inheritance) - the parent object is aware of its children and can veto the addition of a particular child if it would violate a business rule - the child has a "getter" that allows the parent to be accessed directly although it usually isn't needed - the shared interface must contain only read-only methods. The parent object state must not be altered by any access made through the child. In Mushcode: - object inheritance is used to create instance objects from a single prototype object - an object can have multiple simultaneous children (instance objects) - each child can have only one parent at a time (single inheritance) - the parent object is unaware of its children - the child has a public field that allows the parent object to be accessed directly, but this is rarely useful and rarely used by clients - the parent object is effectively read-only. If a client invokes a method via the child that alters state, the altered state is stored in the child object rather than the parent even if the method was located in the parent object. In Microsoft COM/DCOM: - object inheritance is used to simulate class inheritance - an object can have only one child at a time - the parent object is owned by, subservient to, and hidden from the outside world by, the child - each child can have any number of simultaneous parents (multiple inheritance) - the parent object is aware of its child ("outer object") - the parent object(s) can only be accessed via the child, thus the child controls all access to the parent(s) - the child can expose a parent object's implementation of public interfaces as its own (implementation inheritance) - calls to the child's methods can - and often do - alter state in the parent object(s). So in two systems the parent object can be accessed either directly or via any of a number of simultaneous child objects, but its state can never be altered via any child object. In the other system the parent object's state can be altered via a child object, but there is only one child allowed at a time - meaning that each child has its own distinct parent object - and all access to the parent object is controlled by the child. |
|
#7
| |||
| |||
| Daniel T. wrote: > If new methods are being added, then it is more an adaptor than a > decorator. You are right IMHO. What?? This doesn't make sense. How does simply adding new methods qualify for using the Adpater pattern?? The Adapter pattern converts interfaces and The Decorator pattern adds additional responsibilities dynamically. They are indeed related, but there are very notable differences. I suggest that you and Capstar invest in the Head First Design Patterns book. It's an *excellent* learning and reference book. There's even a sample chapter on the Decorator Pattern available at http://www.oreilly.com/catalog/hfdes...apter/ch03.pdf. It will make sense once you read it. Capstar's reference to http://www.codeproject.com/useritems...gpatterns2.asp was indeed correct. I would also like to suggest reading two design pattern articles on JavaBoutique: http://javaboutique.internet.com/tutorials/adapter/ http://javaboutique.internet.com/tutorials/decorator/ Hope this helps... Mike. --- ACGNJ Java Users Group http://www.javasig.org/ |
|
#8
| |||
| |||
| "Michael Redlich" <mpredli{}> wrote: > Daniel T. wrote: > > > If new methods are being added, then it is more an adaptor than a > > decorator. You are right IMHO. > > What?? This doesn't make sense. How does simply adding new methods > qualify for using the Adpater pattern?? The Adapter pattern converts > interfaces and The Decorator pattern adds additional responsibilities > dynamically. They are indeed related, but there are very notable > differences. The whole point of the Adapter pattern is to change the *interface* of a an object so it will be useable in different contexts. Changing an interface means adding/removing methods. The whole point of the Decorator pattern is to change the *behavior* of an object so it will work differently in the same context. Changing behavior means making something different happen in the existing methods. Examine the examples in "Design Patterns" for further understanding. > I suggest that you and Capstar invest in the Head First Design Patterns > book. It's an *excellent* learning and reference book. There's even a > sample chapter on the Decorator Pattern available at > http://www.oreilly.com/catalog/hfdes...apter/ch03.pdf. It will > make sense once you read it. That's some silly stuff. I didn't see anything about the Decorator pattern there though. Just some silly bit about putting a bunch of gets and sets in a class. > Capstar's reference to > http://www.codeproject.com/useritems...gpatterns2.asp was indeed > correct. Think about it, the Decorator is meant to be used through its Component interface. As such, how could it possibly change the interface? [Client]--->[Component]<------------+ ^ | | | +-------+---------+ | | | | [ConcreteComponent] [Decorator]<>-+ Granted, you can add new operations in the Decorator class, but they aren't useable by the client. To steal the example from the Head First chapter you cite above. This would be a proper use of Decorator: class HouseBlend: def cost(self): return 2.43 class DarkRoast: def cost(self): return 2.43 class WithMilk: def __init__(self, aBeverage): self.beverage = aBeverage def cost(self): return self.beverage + .35 class WithMocha: def __init__(self, aBeverage): self.beverage = aBeverage def cost(self): return self.beverage + .18 With the 4 classes above, I can make 8 different types of drinks. Not a getter or setter in sight. -- To send me email, put "sheltie" in the subject. |
|
#9
| |||
| |||
| Daniel T. wrote: > The whole point of the Decorator pattern is to change the *behavior* of > an object so it will work differently in the same context. Changing > behavior means making something different happen in the existing methods. > > Examine the examples in "Design Patterns" for further understanding. Or examine the text? Page 175: "Intent: Attach ADDITIONAL responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for EXTENDING functionality." [emphasis added] Page 176: "Decorator subclasses are free to add operations for specific functionality." This text refers to an example on that page. In that example the base component has only a Draw() method. The decorators add ScrollTo() and DrawBorder() methods. In the Structure diagram on page 177, one decorator has "addedState" and another has "AddedBehavior". Page 178: "Consequences: ... 2. ... Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects." Certainly it is also legitimate for a decorator to change the behavior of existing methods. This is shown in the Structure diagram on p. 177 where we see that DecoratorB has its own implementation of Operation(), and in the Sample Code on p. 181 where BorderDecorator has an override for the Draw() method. It also appears on p. 183 where the decorators exist only to override the HandleBufferFull() method. Finally, we find on page 184: "A decorator is different from an adapter in that a decorator only changes an object's responsibilities, not its interface; an adapter will give an object a COMPLETELY NEW interface." [emphasis added] |
|
#10
| |||
| |||
| "Doug Pardee" <dougpardee{}yahoo.com> wrote: > Daniel T. wrote: > > The whole point of the Decorator pattern is to change the *behavior* of > > an object so it will work differently in the same context. Changing > > behavior means making something different happen in the existing methods. > > > > Examine the examples in "Design Patterns" for further understanding. > > Or examine the text? > > Page 175: "Intent: Attach ADDITIONAL responsibilities to an object > dynamically. Decorators provide a flexible alternative to subclassing > for EXTENDING functionality." [emphasis added] > > Page 176: "Decorator subclasses are free to add operations for specific > functionality." This text refers to an example on that page. In that > example the base component has only a Draw() method. The decorators add > ScrollTo() and DrawBorder() methods. > > In the Structure diagram on page 177, one decorator has "addedState" > and another has "AddedBehavior". Which the client can't use. That's an important point. As I said, sure you can add functions but the client can't actually call the added functions. Sure, you can do all kinds of things in the Decorator, but you *can't* change the interface. > Page 178: "Consequences: ... 2. ... Instead of trying to support all > foreseeable features in a complex, customizable class, you can define a > simple class and add functionality incrementally with Decorator > objects." Yes, add functionality, add responsibilities, add state. Adding interface elements however is pointless, because the client can't access them. > Finally, we find on page 184: "A decorator is different from an adapter > in that a decorator only changes an object's responsibilities, not its > interface; There you go. Decorator doesn't change the interface. -- To send me email, put "sheltie" in the subject. |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.