Content deleted Content added
No edit summary |
→"= delete" redundant in C++ example?: new section |
||
(44 intermediate revisions by 27 users not shown) | |||
Line 1:
{{WikiProject
{{WikiProject Java|auto=inherit|importance=low}}
{{WikiProject Computer science|importance=Low}}
}}
== Code Examples ==
Across wikipedia I think it is to the benefit of all if we maintain a consistent approach of putting language examples as tabs with each language as a tab rather then a massively long list. <!-- Template:Unsigned IP --><small class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/75.168.86.233|75.168.86.233]] ([[User talk:75.168.86.233#top|talk]]) 13:15, 25 October 2024 (UTC)</small> <!--Autosigned by SineBot-->
== Tags ==
Line 46 ⟶ 52:
: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 [[http://www.oreilly.com/catalog/hfdesignpat/chapter/ch03.pdf second reference at the bottom of the page]] has nice diagrams. But you're also very right on this: more comments would be good :) --[[User:Taibr|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 ==
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 ? <!-- Template:Unsigned --><small class="autosigned">— Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[User:Renaat Truijen|Renaat Truijen]] ([[User talk:Renaat Truijen#top|talk]] • [[Special:Contributions/Renaat Truijen|contribs]]) 09:39, 12 November 2020 (UTC)</small> <!--Autosigned by SineBot-->
Example replacement:
<syntaxhighlight lang="java">
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";
}
</syntaxhighlight>
== Example that modifies the base object ==
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
}
/** A concrete example of the BaseClass type
*
*/
class BaseClass implements BaseClassType {
private int x1;
private int x2;
public void
public void
this. }
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 {
}
}
}
// Another concrete Decorator
class Decorator2 extends GenericDecorator {
}
}
}
/
-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();
}
}
</syntaxhighlight>
== Attribution to GoF book? ==
Line 155 ⟶ 232:
== Too many code examples ==
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. --[[User:
:Ok, I've decided to [[WP:BOLD|be bold]] and delete all but the Python example. --[[User:
::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." [[Special:Contributions/195.169.128.3|195.169.128.3]] ([[User talk: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. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/139.149.1.230|139.149.1.230]] ([[User talk:139.149.1.230|talk]]) 08:20, 26 May 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
== Genericity of introduction ==
Line 167 ⟶ 246:
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...) [[User:Atleta.hu|Atleta.hu]] ([[User talk: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. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/58.7.120.231|58.7.120.231]] ([[User talk:58.7.120.231|talk]]) 08:31, 4 January 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
== External Links ==
Line 172 ⟶ 252:
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? [[Special:Contributions/146.12.3.3|146.12.3.3]] ([[User talk: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, [[wikipedia:Be bold|be bold!]]. [[User:BenFrantzDale|—Ben FrantzDale]] ([[User talk:BenFrantzDale|talk]]) 22:21, 25 April 2009 (UTC)
== Wrong UML diagram ==
According the gang of four, the UML diagram on this page describes the [[strategy pattern]] '''not''' the [[decorator pattern]]. <span style="font-size: smaller;" class="autosigned">—Preceding [[Wikipedia:Signatures|unsigned]] comment added by [[Special:Contributions/193.248.173.87|193.248.173.87]] ([[User talk:193.248.173.87|talk]]) 00:13, 29 May 2010 (UTC)</span><!-- Template:UnsignedIP --> <!--Autosigned by SineBot-->
== Python example description ==
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?
[[Special:Contributions/87.151.238.174|87.151.238.174]] ([[User talk:87.151.238.174|talk]]) 12:14, 6 October 2010 (UTC)
: Good point. I fixed it. [[User:BenFrantzDale|—Ben FrantzDale]] ([[User talk:BenFrantzDale|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 ==
Shouldn't WindowDecorator include a getDescription() method?
[[Special:Contributions/206.47.231.164|206.47.231.164]] ([[User talk:206.47.231.164|talk]]) 18:00, 20 December 2010 (UTC)
Yes, it should. If it wants to be Java code that compiles, anyway.
--[[Special:Contributions/207.34.126.10|207.34.126.10]] ([[User talk:207.34.126.10|talk]]) 00:24, 27 January 2011 (UTC)
== Inconsistent: intro says decorate at run time, examples are static decoration ==
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..
[[User:Seanhalle|Seanhalle]] ([[User talk:Seanhalle|talk]]) 18:57, 2 January 2013 (UTC)
== 14:13, 18 February 2013: not according to uml diagram on top of the page ==
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 (--[[Special:Contributions/92.231.222.37|92.231.222.37]] ([[User talk:92.231.222.37|talk]]) 07:37, 22 February 2013 (UTC))
==Delegation in the Java example==
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?
--[[User:Azadismind|Azadi &#123;]] ([[User talk:Azadismind|talk]]) 04:17, 12 October 2013 (UTC)
== External links modified ==
Hello fellow Wikipedians,
I have just modified {{plural:1|one external link|1 external links}} on [[Decorator pattern]]. Please take a moment to review [https://en.wikipedia.org/w/index.php?diff=prev&oldid=753953392 my edit]. If you have any questions, or need the bot to ignore the links, or the page altogether, please visit [[User:Cyberpower678/FaQs#InternetArchiveBot|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 {{tlx|Sourcecheck}}).
{{sourcecheck|checked=false}}
Cheers.—[[User:InternetArchiveBot|'''<span style="color:darkgrey;font-family:monospace">InternetArchiveBot</span>''']] <span style="color:green;font-family:Rockwell">([[User talk:InternetArchiveBot|Report bug]])</span> 00:30, 10 December 2016 (UTC)
[[Special:Contributions/89.12.248.0|89.12.248.0]] ([[User talk:89.12.248.0|talk]]) 16:44, 28 June 2017 (UTC)
== C++ Example for C++11 ==
the C++ Mixin decorator should use the
<syntaxhighlight lang="c++">
override
</syntaxhighlight>
keyword. That way you can make sure that the method you override actually exists in the base classes.
I believe this is helpful.
== "= delete" redundant in C++ example? ==
I've tested it using GCC with <code>-std=c++20</code> and declaring a non default constructor (i.e. <code>BeverageDecorator(std::unique_ptr<Beverage> component_)</code>) suffices to delete the automatically stop generation of a default constructor. I don't know what the standard says about this, but is the <code>= delete</code> really required in the below example?
<syntaxhighlight lang="cpp">class BeverageDecorator: public Beverage {
public:
BeverageDecorator() = delete;
BeverageDecorator(std::unique_ptr<Beverage> component_):
component(std::move(component_)) {}
virtual void drink() = 0;
protected:
void callComponentDrink() {
if (component)
component->drink();
}
private:
std::unique_ptr<Beverage> component;
};</syntaxhighlight> [[User:Wallby|Wallby]] ([[User talk:Wallby|talk]]) 12:18, 12 April 2025 (UTC)
|