Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Special pages
Niidae Wiki
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Decorator pattern
(section)
Page
Discussion
English
Read
Edit
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
View history
General
What links here
Related changes
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==Examples== <!-- Wikipedia is not a list of examples. Do not add examples from your favorite programming language here; this page exists to explain the design pattern, not to show how it interacts with subtleties of every language under the sun. Feel free to add examples here: http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Decorator --> === C++ === This implementation (which uses C++23 features) is based on the pre C++98 implementation in the book. <syntaxhighlight lang="c++"> import std; // Beverage interface. class Beverage { public: virtual void drink() = 0; virtual ~Beverage() = default; }; // Drinks which can be decorated. class Coffee: public Beverage { public: virtual void drink() override { std::print("Drinking Coffee"); } }; class Soda: public Beverage { public: virtual void drink() override { std::print("Drinking Soda"); } }; 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; }; class Milk: public BeverageDecorator { public: Milk(std::unique_ptr<Beverage> component_, float percentage_): BeverageDecorator(std::move(component_)), percentage(percentage_) {} virtual void drink() override { callComponentDrink(); std::print(", with milk of richness {}%", percentage); } private: float percentage; }; class IceCubes: public BeverageDecorator { public: IceCubes(std::unique_ptr<Beverage> component_, int count_): BeverageDecorator(std::move(component_)), count(count_) {} virtual void drink() override { callComponentDrink(); std::print(", with {} ice cubes", count); } private: int count; }; class Sugar: public BeverageDecorator { public: Sugar(std::unique_ptr<Beverage> component_, int spoons_): BeverageDecorator(std::move(component_)), spoons(spoons_) {} virtual void drink() override { callComponentDrink(); std::print(", with {} spoons of sugar", spoons); } private: int spoons = 1; }; int main(int argc, char* argv[]) { std::unique_ptr<Beverage> soda = std::make_unique<Soda>(); soda = std::make_unique<IceCubes>(std::move(soda), 3); soda = std::make_unique<Sugar>(std::move(soda), 1); soda->drink(); std::println(); std::unique_ptr<Beverage> coffee = std::make_unique<Coffee>(); coffee = std::make_unique<IceCubes>(std::move(coffee), 16); coffee = std::make_unique<Milk>(std::move(coffee), 3.); coffee = std::make_unique<Sugar>(std::move(coffee), 2); coffee->drink(); return 0; } </syntaxhighlight> The program output is like <syntaxhighlight lang="c++"> Drinking Soda, with 3 ice cubes, with 1 spoons of sugar Drinking Coffee, with 16 ice cubes, with milk of richness 3%, with 2 spoons of sugar </syntaxhighlight> Full example can be tested on a [https://godbolt.org/z/s848nWozP godbolt page]. === C++ === Two options are presented here: first, a dynamic, runtime-composable decorator (has issues with calling decorated functions unless proxied explicitly) and a decorator that uses mixin inheritance. ==== Dynamic decorator ==== <syntaxhighlight lang="cpp"> import std; struct Shape { virtual ~Shape() = default; virtual std::string getName() const = 0; }; struct Circle: Shape { void resize(float factor) { radius *= factor; } std::string getName() const override { return std::format("A circle of radius {}", radius); } float radius = 10.0f; }; struct ColoredShape: Shape { ColoredShape(const std::string& color, Shape& shape): color(color), shape(shape) {} std::string getName() const override { return std::format("{} which is colored {}", shape.getName(), color); } std::string color; Shape& shape; }; int main() { Circle circle; ColoredShape coloredShape{"red", circle}; std::println("{}", coloredShape.getName()); } </syntaxhighlight> <syntaxhighlight lang="cpp"> import std; struct WebPage { virtual void display()=0; virtual ~WebPage() = default; }; struct BasicWebPage: WebPage { std::string html; void display() override { std::println("Basic WEB page"); } }; struct WebPageDecorator: WebPage { WebPageDecorator(std::unique_ptr<WebPage> webPage): _webPage(std::move(webPage)) {} void display() override { _webPage->display(); } private: std::unique_ptr<WebPage> _webPage; }; struct AuthenticatedWebPage: WebPageDecorator { AuthenticatedWebPage(std::unique_ptr<WebPage> webPage): WebPageDecorator(std::move(webPage)) {} void authenticateUser() { std::println("authentification done"); } void display() override { authenticateUser(); WebPageDecorator::display(); } }; struct AuthorizedWebPage: WebPageDecorator { AuthorizedWebPage(std::unique_ptr<WebPage> webPage): WebPageDecorator(std::move(webPage)) {} void authorizedUser() { std::println("authorized done"); } void display() override { authorizedUser(); WebPageDecorator::display(); } }; int main(int argc, char* argv[]) { std::unique_ptr<WebPage> myPage = std::make_unique<BasicWebPage>(); myPage = std::make_unique<AuthorizedWebPage>(std::move(myPage)); myPage = std::make_unique<AuthenticatedWebPage>(std::move(myPage)); myPage->display(); std::println(); return 0; } </syntaxhighlight> ==== Static decorator (mixin inheritance) ==== This example demonstrates a static Decorator implementation, which is possible due to C++ ability to inherit from the template argument. <syntaxhighlight lang="cpp"> import std; struct Circle { void resize(float factor) { radius *= factor; } std::string getName() const { return std::format("A circle of radius {}", radius); } float radius = 10.0f; }; template <typename T> struct ColoredShape: public T { ColoredShape(const std::string& color): color(color) {} std::string getName() const { return std::format("{} which is colored {}", T::getName(), color); } std::string color; }; int main() { ColoredShape<Circle> redCircle{"red"}; std::println("{}", redCircle.getName()); redCircle.resize(1.5f); std::println("{}", redCircle.getName()); } </syntaxhighlight> === Java === ==== First example (window/scrolling scenario) ==== The following Java example illustrates the use of decorators using the window/scrolling scenario. {{Clear}} <syntaxhighlight lang="java"> // The Window interface class public interface Window { void draw(); // Draws the Window String getDescription(); // Returns a description of the Window } // Implementation of a simple Window without any scrollbars class SimpleWindow implements Window { @Override public void draw() { // Draw window } @Override public String getDescription() { return "simple window"; } } </syntaxhighlight> The following classes contain the decorators for all <code>Window</code> classes, including the decorator classes themselves. <syntaxhighlight lang="java"> // abstract decorator class - note that it implements Window abstract class WindowDecorator implements Window { private final Window windowToBeDecorated; // the Window being decorated public WindowDecorator (Window windowToBeDecorated) { this.windowToBeDecorated = windowToBeDecorated; } @Override public void draw() { windowToBeDecorated.draw(); //Delegation } @Override public String getDescription() { return windowToBeDecorated.getDescription(); //Delegation } } // The first concrete decorator which adds vertical scrollbar functionality class VerticalScrollBarDecorator extends WindowDecorator { public VerticalScrollBarDecorator (Window windowToBeDecorated) { super(windowToBeDecorated); } @Override public void draw() { super.draw(); drawVerticalScrollBar(); } private void drawVerticalScrollBar() { // Draw the vertical scrollbar } @Override public String getDescription() { return super.getDescription() + ", including vertical scrollbars"; } } // The second concrete decorator which adds horizontal scrollbar functionality class HorizontalScrollBarDecorator extends WindowDecorator { public HorizontalScrollBarDecorator (Window windowToBeDecorated) { super(windowToBeDecorated); } @Override public void draw() { super.draw(); drawHorizontalScrollBar(); } private void drawHorizontalScrollBar() { // Draw the horizontal scrollbar } @Override public String getDescription() { return super.getDescription() + ", including horizontal scrollbars"; } } </syntaxhighlight> Here's a test program that creates a <code>Window</code> instance which is fully decorated (i.e., with vertical and horizontal scrollbars), and prints its description: <syntaxhighlight lang="java"> public class DecoratedWindowTest { public static void main(String[] args) { // Create a decorated Window with horizontal and vertical scrollbars Window decoratedWindow = new HorizontalScrollBarDecorator ( new VerticalScrollBarDecorator (new SimpleWindow())); // Print the Window's description System.out.println(decoratedWindow.getDescription()); } } </syntaxhighlight> The output of this program is "simple window, including vertical scrollbars, including horizontal scrollbars". Notice how the <code>getDescription</code> method of the two decorators first retrieve the decorated <code>Window</code>'s description and ''decorates'' it with a suffix. Below is the JUnit test class for the Test Driven Development <syntaxhighlight lang="java"> import static org.junit.Assert.assertEquals; import org.junit.Test; public class WindowDecoratorTest { @Test public void testWindowDecoratorTest() { Window decoratedWindow = new HorizontalScrollBarDecorator(new VerticalScrollBarDecorator(new SimpleWindow())); // assert that the description indeed includes horizontal + vertical scrollbars assertEquals("simple window, including vertical scrollbars, including horizontal scrollbars", decoratedWindow.getDescription()); } } </syntaxhighlight> ==== Second example (coffee making scenario) ==== The next Java example illustrates the use of decorators using coffee making scenario. In this example, the scenario only includes cost and ingredients. {{Clear}} <syntaxhighlight lang="java"> // The interface Coffee defines the functionality of Coffee implemented by decorator public interface Coffee { public double getCost(); // Returns the cost of the coffee public String getIngredients(); // Returns the ingredients of the coffee } // Extension of a simple coffee without any extra ingredients public class SimpleCoffee implements Coffee { @Override public double getCost() { return 1; } @Override public String getIngredients() { return "Coffee"; } } </syntaxhighlight> The following classes contain the decorators for all {{mono|Coffee}} classes, including the decorator classes themselves. <syntaxhighlight lang="java"> // Abstract decorator class - note that it implements Coffee interface public abstract class CoffeeDecorator implements Coffee { private final Coffee decoratedCoffee; public CoffeeDecorator(Coffee c) { this.decoratedCoffee = c; } @Override public double getCost() { // Implementing methods of the interface return decoratedCoffee.getCost(); } @Override public String getIngredients() { return decoratedCoffee.getIngredients(); } } // Decorator WithMilk mixes milk into coffee. // Note it extends CoffeeDecorator. class WithMilk extends CoffeeDecorator { public WithMilk(Coffee c) { super(c); } @Override public double getCost() { // Overriding methods defined in the abstract superclass return super.getCost() + 0.5; } @Override public String getIngredients() { return super.getIngredients() + ", Milk"; } } // Decorator WithSprinkles mixes sprinkles onto coffee. // Note it extends CoffeeDecorator. class WithSprinkles extends CoffeeDecorator { public WithSprinkles(Coffee c) { super(c); } @Override public double getCost() { return super.getCost() + 0.2; } @Override public String getIngredients() { return super.getIngredients() + ", Sprinkles"; } } </syntaxhighlight> Here's a test program that creates a {{mono|Coffee}} instance which is fully decorated (with milk and sprinkles), and calculate cost of coffee and prints its ingredients: <syntaxhighlight lang="java"> public class Main { public static void printInfo(Coffee c) { System.out.println("Cost: " + c.getCost() + "; Ingredients: " + c.getIngredients()); } public static void main(String[] args) { Coffee c = new SimpleCoffee(); printInfo(c); c = new WithMilk(c); printInfo(c); c = new WithSprinkles(c); printInfo(c); } } </syntaxhighlight> The output of this program is given below: <pre> Cost: 1.0; Ingredients: Coffee Cost: 1.5; Ingredients: Coffee, Milk Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles </pre> ===PHP=== <syntaxhighlight lang="php"> abstract class Component { protected $data; protected $value; abstract public function getData(); abstract public function getValue(); } class ConcreteComponent extends Component { public function __construct() { $this->value = 1000; $this->data = "Concrete Component:\t{$this->value}\n"; } public function getData() { return $this->data; } public function getValue() { return $this->value; } } abstract class Decorator extends Component { } class ConcreteDecorator1 extends Decorator { public function __construct(Component $data) { $this->value = 500; $this->data = $data; } public function getData() { return $this->data->getData() . "Concrete Decorator 1:\t{$this->value}\n"; } public function getValue() { return $this->value + $this->data->getValue(); } } class ConcreteDecorator2 extends Decorator { public function __construct(Component $data) { $this->value = 500; $this->data = $data; } public function getData() { return $this->data->getData() . "Concrete Decorator 2:\t{$this->value}\n"; } public function getValue() { return $this->value + $this->data->getValue(); } } class Client { private $component; public function __construct() { $this->component = new ConcreteComponent(); $this->component = $this->wrapComponent($this->component); echo $this->component->getData(); echo "Client:\t\t\t"; echo $this->component->getValue(); } private function wrapComponent(Component $component) { $component1 = new ConcreteDecorator1($component); $component2 = new ConcreteDecorator2($component1); return $component2; } } $client = new Client(); // Result: #quanton81 //Concrete Component: 1000 //Concrete Decorator 1: 500 //Concrete Decorator 2: 500 //Client: 2000 </syntaxhighlight> === Python === The following Python example, taken from [https://wiki.python.org/moin/DecoratorPattern Python Wiki - DecoratorPattern], shows us how to pipeline decorators to dynamically add many behaviors in an object: <syntaxhighlight lang="python"> """ Demonstrated decorators in a world of a 10x10 grid of values 0-255. """ import random def s32_to_u16(x): if x < 0: sign = 0xF000 else: sign = 0 bottom = x & 0x00007FFF return bottom | sign def seed_from_xy(x, y): return s32_to_u16(x) | (s32_to_u16(y) << 16) class RandomSquare: def __init__(s, seed_modifier): s.seed_modifier = seed_modifier def get(s, x, y): seed = seed_from_xy(x, y) ^ s.seed_modifier random.seed(seed) return random.randint(0, 255) class DataSquare: def __init__(s, initial_value=None): s.data = [initial_value] * 10 * 10 def get(s, x, y): return s.data[(y * 10) + x] # yes: these are all 10x10 def set(s, x, y, u): s.data[(y * 10) + x] = u class CacheDecorator: def __init__(s, decorated): s.decorated = decorated s.cache = DataSquare() def get(s, x, y): if s.cache.get(x, y) == None: s.cache.set(x, y, s.decorated.get(x, y)) return s.cache.get(x, y) class MaxDecorator: def __init__(s, decorated, max): s.decorated = decorated s.max = max def get(s, x, y): if s.decorated.get(x, y) > s.max: return s.max return s.decorated.get(x, y) class MinDecorator: def __init__(s, decorated, min): s.decorated = decorated s.min = min def get(s, x, y): if s.decorated.get(x, y) < s.min: return s.min return s.decorated.get(x, y) class VisibilityDecorator: def __init__(s, decorated): s.decorated = decorated def get(s, x, y): return s.decorated.get(x, y) def draw(s): for y in range(10): for x in range(10): print("%3d" % s.get(x, y), end=' ') print() # Now, build up a pipeline of decorators: random_square = RandomSquare(635) random_cache = CacheDecorator(random_square) max_filtered = MaxDecorator(random_cache, 200) min_filtered = MinDecorator(max_filtered, 100) final = VisibilityDecorator(min_filtered) final.draw() </syntaxhighlight> '''Note:''' The Decorator Pattern (or an implementation of this design pattern in Python - as the above example) should not be confused with [[Python syntax and semantics#Decorators|Python Decorators]], a language feature of Python. They are different things. Second to the Python Wiki: <blockquote>The Decorator Pattern is a pattern described in the Design Patterns Book. It is a way of apparently modifying an object's behavior, by enclosing it inside a decorating object with a similar interface. This is not to be confused with Python Decorators, which is a language feature for dynamically modifying a function or class.<ref>{{cite web|url=https://wiki.python.org/moin/DecoratorPattern|title=DecoratorPattern - Python Wiki|website=wiki.python.org}}</ref></blockquote> === Crystal === <syntaxhighlight lang="ruby"> abstract class Coffee abstract def cost abstract def ingredients end # Extension of a simple coffee class SimpleCoffee < Coffee def cost 1.0 end def ingredients "Coffee" end end # Abstract decorator class CoffeeDecorator < Coffee protected getter decorated_coffee : Coffee def initialize(@decorated_coffee) end def cost decorated_coffee.cost end def ingredients decorated_coffee.ingredients end end class WithMilk < CoffeeDecorator def cost super + 0.5 end def ingredients super + ", Milk" end end class WithSprinkles < CoffeeDecorator def cost super + 0.2 end def ingredients super + ", Sprinkles" end end class Program def print(coffee : Coffee) puts "Cost: #{coffee.cost}; Ingredients: #{coffee.ingredients}" end def initialize coffee = SimpleCoffee.new print(coffee) coffee = WithMilk.new(coffee) print(coffee) coffee = WithSprinkles.new(coffee) print(coffee) end end Program.new </syntaxhighlight> Output: <pre> Cost: 1.0; Ingredients: Coffee Cost: 1.5; Ingredients: Coffee, Milk Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles </pre> ===C#=== <syntaxhighlight lang="csharp"> namespace WikiDesignPatterns; public interface IBike { string GetDetails(); double GetPrice(); } public class AluminiumBike : IBike { public double GetPrice() => 100.0; public string GetDetails() => "Aluminium Bike"; } public class CarbonBike : IBike { public double GetPrice() => 1000.0; public string GetDetails() => "Carbon"; } public abstract class BikeAccessories : IBike { private readonly IBike _bike; public BikeAccessories(IBike bike) { _bike = bike; } public virtual double GetPrice() => _bike.GetPrice(); public virtual string GetDetails() => _bike.GetDetails(); } public class SecurityPackage : BikeAccessories { public SecurityPackage(IBike bike) : base(bike) { } public override string GetDetails() => base.GetDetails() + " + Security Package"; public override double GetPrice() => base.GetPrice() + 1; } public class SportPackage : BikeAccessories { public SportPackage(IBike bike) : base(bike) { } public override string GetDetails() => base.GetDetails() + " + Sport Package"; public override double GetPrice() => base.GetPrice() + 10; } public class BikeShop { public static void UpgradeBike() { var basicBike = new AluminiumBike(); BikeAccessories upgraded = new SportPackage(basicBike); upgraded = new SecurityPackage(upgraded); Console.WriteLine($"Bike: '{upgraded.GetDetails()}' Cost: {upgraded.GetPrice()}"); } } </syntaxhighlight> Output: <pre> Bike: 'Aluminium Bike + Sport Package + Security Package' Cost: 111 </pre> === Ruby === <syntaxhighlight lang="ruby"> class AbstractCoffee def print puts "Cost: #{cost}; Ingredients: #{ingredients}" end end class SimpleCoffee < AbstractCoffee def cost 1.0 end def ingredients "Coffee" end end class WithMilk < SimpleDelegator def cost __getobj__.cost + 0.5 end def ingredients __getobj__.ingredients + ", Milk" end end class WithSprinkles < SimpleDelegator def cost __getobj__.cost + 0.2 end def ingredients __getobj__.ingredients + ", Sprinkles" end end coffee = SimpleCoffee.new coffee.print coffee = WithMilk.new(coffee) coffee.print coffee = WithSprinkles.new(coffee) coffee.print </syntaxhighlight> Output: <pre> Cost: 1.0; Ingredients: Coffee Cost: 1.5; Ingredients: Coffee, Milk Cost: 1.7; Ingredients: Coffee, Milk, Sprinkles </pre>
Summary:
Please note that all contributions to Niidae Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Encyclopedia:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Search
Search
Editing
Decorator pattern
(section)
Add topic