11.4.2 - Decorator Pattern
Enroll to start learning
You’ve not yet enrolled in this course. Please enroll for free to listen to audio lessons, classroom podcasts and take practice test.
Interactive Audio Lesson
Listen to a student-teacher conversation explaining the topic in a relatable way.
Understanding the Decorator Pattern
🔒 Unlock Audio Lesson
Sign up and enroll to listen to this audio lesson
Today, we’ll explore the Decorator Pattern. Can anyone explain what they think it does?
I think it adds features to objects, but I’m not sure how it works.
Great starting point! Yes, it allows us to add responsibilities to individual objects dynamically. To remember this, think of it like putting layers on a cake—each layer adds something without changing the cake itself.
So, it doesn’t modify the original object?
Exactly! That's a core principle of the Decorator Pattern. It meets the Open/Closed Principle where we can extend an object’s behavior without modifying its code. Let's dive deeper into the implementation.
Components of the Decorator Pattern
🔒 Unlock Audio Lesson
Sign up and enroll to listen to this audio lesson
The Decorator Pattern consists of several components. Can anyone name the three key components?
Is the first one the component interface?
Correct! The Component Interface defines the common interface for all decorators and concrete components. What about the second component?
I think it’s the concrete component?
Exactly! This represents the object to which functionalities are added. And lastly?
The decorator itself adds functionality to the component!
"Well done! Let's briefly summarize.
Example of the Decorator Pattern
🔒 Unlock Audio Lesson
Sign up and enroll to listen to this audio lesson
Let's look at a practical example in Java. We have a `Coffee` interface, and `SimpleCoffee` implements it. How might we add milk to our coffee?
Using the `MilkDecorator` to add milk to our `SimpleCoffee`?
Correct! The `MilkDecorator` adds the milk functionality without altering the original `SimpleCoffee` class. Do you see the benefit of this approach?
Yes, we can combine multiple decorators too!
"Exactly! This means we can keep extending our object in varied ways. Let’s summarize:
Introduction & Overview
Read summaries of the section's main ideas at different levels of detail.
Quick Overview
Standard
The Decorator Pattern is a structural design pattern that enables the addition of new functionalities to an object at runtime. This allows for a more flexible and reusable design, as decorators can be combined in various ways to enhance an object without modifying the underlying code.
Detailed
Decorator Pattern
The Decorator Pattern is a structural design pattern that provides a way to add new functionalities to objects dynamically. Rather than modifying the object’s existing structure, decorators are used to wrap existing objects in order to extend their behavior. This provides flexibility and adheres to the Open/Closed Principle, which states that software entities should be open for extension but closed for modification.
Key Components:
- Component Interface: This defines the interface for objects that can have responsibilities added to them.
- Concrete Component: This is a class that implements the component interface, representing the core object to which responsibilities can be added.
- Decorator: This class implements the same interface as the component and has a reference to a component object. It also defines additional behaviors.
Example in Java:
- Component Interface:
Coffeewith methods for retrieving a description and cost. - Concrete Component:
SimpleCoffeeimplementing theCoffeeinterface. - Decorator:
MilkDecoratortakes aCoffeeobject in its constructor and wraps it, adding extra functionality.
Significance: The Decorator Pattern promotes code reusability and allows enhanced functionality to be added to an existing object without changes to its structure, thus enabling a flexible design approach.
Youtube Videos
Audio Book
Dive deep into the subject with an immersive audiobook experience.
Overview of the Decorator Pattern
Chapter 1 of 3
🔒 Unlock Audio Chapter
Sign up and enroll to access the full audio experience
Chapter Content
The Decorator Pattern adds responsibilities to objects dynamically.
Detailed Explanation
The Decorator Pattern is a structural design pattern used to add new functionality or behavior to individual objects without altering their structure. This is useful when you want to enhance the capabilities of a class without using inheritance. Instead of creating subclasses for every possible combination of functionality, decorators allow you to build complex behavior dynamically at runtime.
Examples & Analogies
Think of a basic coffee drink. On its own, it has a simple flavor. Now, imagine you want to make that coffee special by adding extra ingredients like milk or caramel. Rather than creating entirely new drinks for each combination (like 'milk coffee' or 'caramel coffee'), you can simply add the ingredients one by one to your existing base coffee. This flexibility is akin to how the Decorator Pattern works, where we stack decorators to enhance the original object without altering its core nature.
Interface and Base Implementation
Chapter 2 of 3
🔒 Unlock Audio Chapter
Sign up and enroll to access the full audio experience
Chapter Content
interface Coffee {
String getDescription();
int getCost();
}
class SimpleCoffee implements Coffee {
public String getDescription() { return "Simple Coffee"; }
public int getCost() { return 5; }
}
Detailed Explanation
In this chunk, we see an interface named Coffee, which defines two methods: getDescription() and getCost(). The SimpleCoffee class implements this interface and provides basic descriptions and costs for a simple coffee drink. This sets the foundation for how coffee objects will be represented in terms of their behavior and attributes.
Examples & Analogies
Imagine a coffee shop menu. The Coffee interface represents the generic entry on that menu that tells customers what to expect from any type of coffee. The SimpleCoffee is the simplest version of that coffee, just like how a 'black coffee' could be a basic item in a coffee shop, giving a straightforward idea of what a customer would get.
The Milk Decorator
Chapter 3 of 3
🔒 Unlock Audio Chapter
Sign up and enroll to access the full audio experience
Chapter Content
class MilkDecorator implements Coffee {
private Coffee coffee;
public MilkDecorator(Coffee coffee) { this.coffee = coffee; }
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
public int getCost() {
return coffee.getCost() + 2;
}
}
Detailed Explanation
This chunk introduces the MilkDecorator class, which also implements the Coffee interface. It takes an existing Coffee object as input and enhances it. The getDescription() method appends ', Milk' to the description of the coffee passed to the decorator, while the getCost() method adds an additional cost for the milk. This showcases how the pattern allows for extending functionality without modifying the original object.
Examples & Analogies
Returning to our coffee shop example, adding milk to a coffee is akin to a customer asking to personalize their drink. Just as you could order a simple coffee and then request to add milk (which changes both the flavor and price slightly), the MilkDecorator does the same in code, enhancing the basic coffee functionality dynamically.
Key Concepts
-
Dynamic Responsibility Addition: The Decorator Pattern allows adding responsibilities dynamically to objects without changing their structure.
-
Component Interface: This is the interface defining the common behaviors for both decorators and concrete objects.
-
Concrete Component: This refers to the actual object that is being decorated.
-
Decorators: These classes implement the component interface and add additional behavior to concrete components.
Examples & Applications
In a coffee shop, a customer orders a simple coffee. Later, they decide to add milk and sugar. Each addition can be seen as a new layer of functionality, applied at runtime using decorators.
Java I/O streams utilize the Decorator Pattern where classes like BufferedReader add functionalities such as reading lines from an existing InputStream.
Memory Aids
Interactive tools to help you remember key concepts
Rhymes
Decorate a cake, layer by layer, to add flavor; similarly, enhance your code without the labor.
Stories
Imagine a plain cup of coffee. A customer adds milk, then sugar, and finally whipped cream. With each addition, the coffee becomes more enjoyable without changing its original form.
Memory Tools
C-C-D: Component, Concrete Component, Decorator - this helps you remember the essential parts of the Decorator Pattern.
Acronyms
D.A.C
Decorator Adds Complexity - highlights that while adding new functionality
we can also introduce complexity.
Flash Cards
Glossary
- Decorator Pattern
A structural design pattern that allows behavior to be added to individual objects dynamically without modifying their structure.
- Component Interface
An interface that defines the common behaviors for concrete components and decorators.
- Concrete Component
An object that implements the component interface and can have responsibilities added to it.
- Decorator
A class that implements the component interface and has a reference to a component object, adding new behavior.
Reference links
Supplementary resources to enhance your learning experience.