Talk:Decorator pattern
![]() | This article is rated Start-class on Wikipedia's content assessment scale. It is of interest to the following WikiProjects: | ||||||||||||||||||||||||||||||
|
Tags
[edit]My goodness. If I don't get to NPOVing/encyclopedicafying the "taco" example, could someone, please? Dysprosia 10:31, 4 Nov 2003 (UTC)
- The latest PNA cycle improved a lot, but there's still a big gap between here and goodness ("objects can have attributes that change something about them" sounds like something from a philosophy article). Let me work it over a bit... JRM
OK, I've revamped it, hopefully clarifying it (and removing the absurd "taco" example altogether). I've also removed links to bean pattern (much too specific reference to Enterprise Java Beans) and self joining data (I've never even heard of this and I doesn't Google in any relevant way—if this is not just another fifteen-minutes buzzword and someone else has, please do write an article about it and (if it's related) reinstate the link).
I'm still not perfectly happy with what I've written (it's still not accessible enough to the Ignorant Outside World), but this is simply because I'm not a writer (and don't have access to Design Patterns at present). You there! Improve it! I don't know where you're from, but here on Wikipedia, we collaborate! :-) JRM 14:15, 2004 Nov 16 (UTC)
Ech, I just saw proxy pattern. We have a long way ahead of us. Anyone feel like a new WikiProject? :-) JRM 14:15, 2004 Nov 16 (UTC)
OK, I've added the section headings suggested by the Gang of Four on the Design pattern (computer science) page, and rearranged the existing content under these headings. However, we still need additional content. AmunRa84, 14:07, 2005 Jan 9 (UTC)
The layout looks fine so I'm removing the "wikify" tag. If the article still neads a lot of work, we can put "cleanup" instead? Jeeves 02:26, 9 Jun 2005 (UTC)
UML diagram
[edit]The UML Arrow from Window to DecoratedWindow should be a inheritance arrow, not an aggregation arrow. --82.130.71.200 (talk) 09:18, 25 May 2009 (UTC)
This page lacks the UML diagram. I would add it but I don't know if I can copy it from another site, and I don't have the time to do it myself and get a printscreen from it
- Done ACiD2
If the Decorator implements the Component, shouldn't "doStuff()" be called "operation()"? It does so in the GoF book. MatthiasO
the UML diagram is wrong, as the method names are not consistent:
- Component:Operation
- ConcreteComponent:Operation
- Decorator:DoSomething
- ConcreteDecoratorA/B:DoStuff
all these methods should have the same name !!!! Malo
- Decorator:DoSomething seems alright, as it doesn't implement "+Operation()". Implementation of Operation() is supposed to happen in the ConcreteDecorator. The DoStuff() seems indeed wrong, and that diagram doesn't make sense to me. Better look at the window-example, or the c++ example.
- I don't have the software installed to repaint it, but I remove the image now, as it does more damage than merit.
- Phresnel (talk) 09:31, 9 February 2009 (UTC)
- Please next time have the courtesy to try fix the image, instead of just deleting it from the wiki. It's one thing to remove it from the article page if it's wrong, but to mark it for deletion because of a few text errors inside it? That's depriving everyone of that image. Wikipedia:Graphic Lab does image alterations, especially vector images, which I am a part of. I have no intention of re-uploading this image, so enjoy that. Too many of my images contributions to this wiki have been deleted for SILLY reasons. Have a nice day.XcepticZP (talk) 16:43, 23 March 2009 (UTC)
Explicit implementation?
[edit]Hi guys, hope this is the right place for a comment (my first on Wikipedia): the Java code provided may be better off with an explicit "extend Window" in the decorator class declarations. The text above the code mentions that it is a requirement, but the snippet does not have it. Hope this helps. Taibr 03:39, 25 January 2006 (UTC)
- I think the text may be incorrect. You can see that myWindow is a private variable of the Window class so it doesn't necessarily need to be a subclass. It is this variable which is to become decorated. As another example, one could argue that a beach ball class is a decoration on a sphere class but BeachBall doesn't necessarily need to extend Sphere (nor vice versa), just use a sphere and apply it's own "proprietory" attributes. There probably should be a Window interface, a new class that implements Window, and the Vertical/Horizontal scroller classes that implements Window and uses a variable which is of type {the new class}. Hopefully we can get more comments here.--Will2k 04:51, 25 January 2006 (UTC)
- I am not an expert, but I think you're right: the original class and its decorated version should share a common superclass. This is required because you want to dynamically use (and cascade) decorators at run-time, yet having the resulting decorated class still of the same (super)type as the original class. So, you're right that your (concrete) decorator should not necessarily extend Window, so long Window and itself have a common superclass, which defines the utility methods you want to use. From what I see in the literature, the superclass "S" can be either abstract or an interface (in Java); and the concrete decorator may inherit an abstract decorator which is the one extending or implementing "S". The [second reference at the bottom of the page] has nice diagrams. But you're also very right on this: more comments would be good :) --Taibr 05:07, 27 January 2006 (UTC)
Depends on the lang. the types have to be related enough so that you can treat a decorated class and an undecorated class identically. So in java they have to share an interface or class hirarchy. In C++ they would have to share a class hirarchy. In Python/ruby they could be totally unrelated and just happen to have the same functions defined on both. bhunt 7/30/2007
Java example's WindowDecorator class is unnecessary
[edit]What benefit does this class provide over having the decorators implement Window directly? (honestly trying to learn here)
- I was really helped with the example, and indeed, with all respect, your example replacement shows precisely that indeed you didn't get the point. You are creating a local new data
member "private Window windowToBeDecorated;". With this approach, the Horizontal will also contain such a field and so for the Horizontal-and-Vertical window you will now do what? Mayb eyou make a subclass of one of those and so the number of classes explodes, and maybe you will again make a local field so store 2 times the same field ? — Preceding unsigned comment added by Renaat Truijen (talk • contribs) 09:39, 12 November 2020 (UTC) Example replacement:
class VerticalScrollBarWindowDecorator implements Window{
private Window windowToBeDecorated;
public VerticalScrollBarDecorator (Window windowToBeDecorated) {
this.windowToBeDecorated = windowToBeDecorated;
}
@Override
public void draw() {
windowToBeDecorated.draw();
drawVerticalScrollBar();
}
private void drawVerticalScrollBar() {
// Draw the vertical scrollbar
}
@Override
public String getDescription() {
return windowToBeDecorated.getDescription() + ", including vertical scrollbars";
}
Example that modifies the base object
[edit]I like the explanation, but not the example: drawVerticalScrollBar() and drawHorizontalScrollBar() seems to be designed to show the plug-in behavoir of the pattern but they do nothing. It is only getDescription() the relevant method in the example. I would add that a modular Decorator pattern can't extend functionallity by new methods, but only by overriden existing ones. To add new method functionallity you would need to define a hierarchy of decorators, not as functional as the plug-in aproach.
Below a more detailled discussion along with an example in Java that really modifies the base object in a modular way.
/** The type of base class
*
*/
interface BaseClassType{
public void function() ;
public void incX1(int x);
public void incX2(int x);
public void showState() ;
}
/** A concrete example of the BaseClass type
*
*/
class BaseClass implements BaseClassType {
private int x1;
private int x2;
public void function() { }
public void incX1(int x) {
this.x1 += x;
}
public void incX2(int x) {
this.x2 += x;
}
public void showState() {
String message = "x1=" + this.x1 + "; x2=" + this.x2;
System.out.println(message);
}
}
/**public BaseClass(BaseClass baseObject){this=baseObject;}
The generic decorator class for classes of type BaseClassType. It must fullfill these conditions:
- Be of type BaseClass by extending BaseClass.
Implementing BaseClassType is not eough if the decorator has to modify the base object.
- Contain a "supplanter": a reference to an object of the base class. This object is
the one that will be decorated, and will supplant the base object of the superclass.
- Redirect the BaseClass methods to the supplanter, so the superclass BaseClass methods
would use/act on it.
GenericDecorator implementing a common interface with BaseClass is not enough, the
supplanter has to use the BaseClass methods and modify the functionallity so some of them
- Contain a constructor that initilizes the component pointer making it to
to the passed object. The generic decorator can also afford for adittional methods
shared by all the derived decorators (the incXY method here).
*/
abstract class GenericDecorator implements BaseClassType {
protected BaseClassType supplanter; // the baseObject reference
public void incX1(int x) {
supplanter.incX1(x);
}
public void incX2(int x) {
supplanter.incX2(x);
}
public void function() {
supplanter.function();
}
public void showState() {
this.supplanter.showState();
}
public void incXY(int x){incX1(x);incX2(x);}
public GenericDecorator(BaseClassType baseObject) {
this.supplanter = baseObject;
}
}
/**A concrete Decorator, it has to:
- Extend the generic decorator
- Override some BaseClass methods adding them a certain functionallity by
+Apllying some transformation
+ Redirecting them to the supplanter, so that other decorators in the chain
will be able to perform make their own actions.
In this example overrides function() by incrementing variable x1 by 5
- Contain a constructor that refers to the parent GenericDecorator constructor.
*/
class Decorator1 extends GenericDecorator {
public void function() {
supplanter.incX1(5);
supplanter.function();
}
//constructor
public Decorator1(BaseClassType baseObject) {
super(baseObject);
}
}
// Another concrete Decorator
class Decorator2 extends GenericDecorator {
public void function() {
supplanter.incX2(4);
supplanter.function();
}
//constructor
public Decorator2(BaseClassType baseObject) {
super(baseObject);
}
}
/**Test example
-The Decorator pattern subclass at runtime the single object baseObject
into objectDecorated_12 without subclassing the entire class BaseClass.
-The x1 and x2 variables of baseObject are not modified in main():
the supplanter object has supplanted them at all effects.
-Decorators can be applied sequentally in a modular way, like
independent plug-ins connected along in a chain.
-You can't use the Decorator pattern to extend functionallity
by adding new methods in a modular way like this.
- To add new method functionallity to the pattern, you will need
to define a hierarchy of decorators.
*/
public class DecoratorPattern2 {
public static void main(String[] args) {
BaseClassType baseObject = new BaseClass();
GenericDecorator objectDecorated_1 = new Decorator1(baseObject);
GenericDecorator objectDecorated_12 = new Decorator2(objectDecorated_1);
objectDecorated_12.function();
//objectDecorated_12.incXY(3);
objectDecorated_12.showState();
}
}
Attribution to GoF book?
[edit]The Window / ScrollableWindow example seems stripped right out of the GoF Design Patterns book. Should this be attributed here, or is the example so ubiqutious that it doesn't need such treatment?
Mistake in the diagram
[edit]The diagram should show the operation() in the decorator tree instead of the doStuff() method. Oldani 17:30, 20 Mar 2007 (UTC)
same remark for Decorator:DoSomething() it should also be renamed Decorator:operation(). Malo —Preceding unsigned comment added by 82.127.102.32 (talk) 13:19, 8 November 2007 (UTC)
This diagram is indeed wrong and deceptive. Would anyone mind if we replace it with the one from the dutch wikipedia (the diagram is in in English). See http://nl.wikipedia.org/wiki/Decorator ? It's very clear to explain the Decorator pattern. --Marcvangrieken (talk) 15:11, 1 April 2008 (UTC)
Mistake in the diagram of the example
[edit]I think WindowDecorator is missing an "implements" link to Window: the corresponding Java code states "abstract class WindowDecorator implements Window", and the general example above shows the same relationship between Decorator and Component. Ma82 (talk) 13:02, 2 June 2008 (UTC)
Another thing with the diagram: drawVertical and DrawHorizontal should be private, since used only by the containing classes. —Preceding unsigned comment added by 213.30.132.28 (talk) 14:24, 4 November 2008 (UTC)
The WindowDecorator is shown to have aggregation relationship with Windows, where as it should be inheritance/ implementation. this is serious as it clearly defies the pattern rules. —Preceding unsigned comment added by Karandeepmalik (talk • contribs) 07:31, 14 April 2009 (UTC)
Too many code examples
[edit]This page seems to have started down an all-too-common path of turning into a repository for a multitude of redundant examples in numerous languages. We need to pick the one clearest example, be it in pseudocode or some actual language, and get rid of the others. --Doradus (talk) 19:49, 9 January 2009 (UTC)
- Ok, I've decided to be bold and delete all but the Python example. --Doradus (talk) 13:52, 14 March 2009 (UTC)
- The Python example should go as well. It uses a language mechanism with the same superficial behaviour and the same name, but it's not a precise example of the design pattern in question. Quoted from Python_syntax_and_semantics#Decorators: "Despite the name, Python decorators are not an implementation of the decorator pattern." 195.169.128.3 (talk) 08:38, 29 July 2009 (UTC)
I doubt the Python example even is an example of the pattern as the decoration occurs during the definition of the class itself, and not at 'run-time'. Granted, everything is at run-time in Python, but this example would require edit of the source containing the original definition of the class. This is not decoration. —Preceding unsigned comment added by 139.149.1.230 (talk) 08:20, 26 May 2010 (UTC)
Genericity of introduction
[edit]I think the introduction is not generic enough, i.e. uses too much implementation and language specific terms. Talking about delegating the method calls to the decorated object would be better. Also I don't really like the use of pointers, using reference might be better (I know, that in some languages, like C&C++ they both exist don't mean the same). Or just broadly describing it as the decorator delegating to the decorated object, period. The third thing is that the decorator doesn't have to extend the decorated object, it just has to have the same interface. This is clearly shown e.g. java example (not to talk about the dynamic language ones), where the WindowDecorator doesn't do anything but holds a reference to the decorated object.
A decorator base class can be useful for implementing decorators for complicated interfaces if it contained a default delegating implementation for all the methods. But it's a different question I think (and as I said in the java example the abstract base doesn't have any behaviour...) Atleta.hu (talk) 23:42, 9 March 2009 (UTC)
I found the python example to be anything but helpful, a more concise snippet would be nice. —Preceding unsigned comment added by 58.7.120.231 (talk) 08:31, 4 January 2010 (UTC)
External Links
[edit]I'm not sure what protocol is here, but the information in the link "Sample Chapter "C# Design Patterns: The Decorator Pattern" (C#) by James W. Cooper" appears to be misleadingly wrong. He ends up creating a simple class inheritance rather than a decorator. If someone could verify and then remove the link? 146.12.3.3 (talk) 19:26, 23 April 2009 (UTC)
- I just read it. It's not clear to me if it is wrong or just a bad/incomplete explanation. I'll remove the link. In the future, be bold!. —Ben FrantzDale (talk) 22:21, 25 April 2009 (UTC)
Wrong UML diagram
[edit]According the gang of four, the UML diagram on this page describes the strategy pattern not the decorator pattern. —Preceding unsigned comment added by 193.248.173.87 (talk) 00:13, 29 May 2010 (UTC)
Python example description
[edit]Even for Wikipedia standards, it can't get more confusing than this:
"Not to be confused with the concept of "decorators" in Python. This is an example using Python's concept of "decorators," but not using the Decorator Pattern, since this is modifying the class directly not an instance of the class."
What? 87.151.238.174 (talk) 12:14, 6 October 2010 (UTC)
- Good point. I fixed it. —Ben FrantzDale (talk) 11:46, 7 October 2010 (UTC)
Um they aren't completely distinct though. I have to think the language feature was named after the design pattern, since it does indeed decorate the underlying object similar to the Decorator design pattern, but with syntactic sugar.
Incomplete interface
[edit]Shouldn't WindowDecorator include a getDescription() method?
206.47.231.164 (talk) 18:00, 20 December 2010 (UTC)
Yes, it should. If it wants to be Java code that compiles, anyway.
--207.34.126.10 (talk) 00:24, 27 January 2011 (UTC)
Inconsistent: intro says decorate at run time, examples are static decoration
[edit]One of the key values of the decorator pattern stated, was that decoration could be done during the run. However, both Java examples require the decorated object to be passed to the constructor of the decorator. Hence, decoration can only be done statically in the code. It cannot be done during the run.
But it's not just the Java examples, by the UML diagram that encodes this static-only restriction. Inconsistent.
To make decoration possible during the run, the linkage would have to be something along the lines of a linked-list, such as in the chain-of-responsibility pattern.. except, each link in the chain is a decorator, and the chain starts with the decorated object. As control moves down the chain, each decorator receives an object from up-chain, and adds its own decoration. For the scrollbar example, each would receive, for example, an object that represents the state of a canvas.. what area remains free to be painted by the decorator.. and perhaps a means of connecting decorations like scrollbars to the text-area that they control.. the current example seems a bit bogus, actually, because information and control has to be exchanged between the decorators and the decorated window.. a scrollbar doesn't just paint itself! It has to cause the painter of the text area to re-paint in a particular way.. so it has to be connected to the painter of the text area in an intimate way..
Seanhalle (talk) 18:57, 2 January 2013 (UTC)
14:13, 18 February 2013: not according to uml diagram on top of the page
[edit]Wouldn't it be more correct to change the UML diagram instead of the example Java code to get examples that are according to the UML diagram on top of the page?
I think, now both the UML diagram and the two examples ("coffee making scenario" and "window/scrolling scenario") are wrong.
Michael (--92.231.222.37 (talk) 07:37, 22 February 2013 (UTC))
Delegation in the Java example
[edit]Is there a particular reason why the Java example with Coffee doesn't use delegation in its concrete decorator classes? Why should Milk be an instance of coffee and be tied to coffee me</ref>chanisms? Why doesn't this example follow the one preceding it with Windows where Milk should have a Coffee member, and delegate & override the coffee functionality to its member? --Azadi { (talk) 04:17, 12 October 2013 (UTC)
External links modified
[edit]Hello fellow Wikipedians,
I have just modified one external link on Decorator pattern. Please take a moment to review my edit. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit this simple FaQ for additional information. I made the following changes:
- Added archive https://web.archive.org/web/20150707165957/http://sam-burns.co.uk/57/how-to-implement-a-decorator-pattern/ to http://sam-burns.co.uk/57/how-to-implement-a-decorator-pattern/
When you have finished reviewing my changes, please set the checked parameter below to true or failed to let others know (documentation at {{Sourcecheck}}
).
This message was posted before February 2018. After February 2018, "External links modified" talk page sections are no longer generated or monitored by InternetArchiveBot. No special action is required regarding these talk page notices, other than regular verification using the archive tool instructions below. Editors have permission to delete these "External links modified" talk page sections if they want to de-clutter talk pages, but see the RfC before doing mass systematic removals. This message is updated dynamically through the template {{source check}}
(last update: 5 June 2024).
- If you have discovered URLs which were erroneously considered dead by the bot, you can report them with this tool.
- If you found an error with any archives or the URLs themselves, you can fix them with this tool.
Cheers.—InternetArchiveBot (Report bug) 00:30, 10 December 2016 (UTC)
89.12.248.0 (talk) 16:44, 28 June 2017 (UTC)
C++ Example for C++11
[edit]the C++ Mixin decorator should use the
override
keyword. That way you can make sure that the method you override actually exists in the base classes. I believe this is helpful.
Start a discussion about improving the Decorator pattern page
Talk pages are where people discuss how to make content on Wikipedia the best that it can be. You can use this page to start a discussion with others about how to improve the "Decorator pattern" page.