0% found this document useful (0 votes)
11 views6 pages

Design Patterns in C# Part 3 - Enhancing Functionality With The Decorator Pattern - by João Melo - Medium

This document discusses the Decorator Pattern in C#, a structural design pattern that allows for the dynamic addition of behavior to objects without altering the behavior of other objects in the same class. It provides a practical example using a coffee shop application, demonstrating how to create a base coffee class and various decorators for condiments like milk and sugar. The article emphasizes the flexibility and reusability of the Decorator Pattern and hints at the next topic in the series, the Observer Pattern.

Uploaded by

ekrrmerder
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views6 pages

Design Patterns in C# Part 3 - Enhancing Functionality With The Decorator Pattern - by João Melo - Medium

This document discusses the Decorator Pattern in C#, a structural design pattern that allows for the dynamic addition of behavior to objects without altering the behavior of other objects in the same class. It provides a practical example using a coffee shop application, demonstrating how to create a base coffee class and various decorators for condiments like milk and sugar. The article emphasizes the flexibility and reusability of the Decorator Pattern and hints at the next topic in the series, the Observer Pattern.

Uploaded by

ekrrmerder
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

Open in app

Search

Your membership will expire on January 11, 2025 Reactivate membership

Design Patterns in C# Part 3: Enhancing


Functionality with the Decorator Pattern
João Melo · Follow
4 min read · Jun 24, 2024

Listen Share More

Mastering Design Patterns in C#: A Comprehensive Series

Introduction

Welcome back to the Ultimate Guide to Design Patterns in C#! In this series, we
explore various design patterns that can significantly enhance your software design
and development. In the first two parts, we unleashed the power of the Strategy
Pattern and simplified object creation with the Factory Method Pattern. Today, we’ll
https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 1/13
19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

dive into the Decorator Pattern and see how it can dynamically add behavior to
objects.

💡Type — Structural patterns deal with object composition or how classes and
objects can be combined to form larger structures. These patterns help ensure that
if one part of a system changes, the entire system doesn’t need to change.

What is the Decorator Pattern?

The Decorator Pattern is a structural design pattern that allows behavior to be


added to individual objects, either statically or dynamically, without affecting the
behavior of other objects from the same class. It achieves this by creating a set of
decorator classes that are used to wrap concrete components.

When to Use the Decorator Pattern?

The Decorator Pattern is particularly useful when you want to add responsibilities to
objects dynamically and transparently, without affecting other objects. It’s also
beneficial when extending behavior using inheritance is impractical due to a large
number of independent extensions or when you need to add responsibilities to an
object that you may not know about at compile time.

Real-world example in C# — Coffee Shop

Imagine we are building a coffee shop application where customers can order
different types of coffee and customize their drinks with various condiments like
milk, sugar, and whipped cream. Instead of creating a class for each possible
combination of coffee and condiments, we can use the Decorator Pattern to add
condiments dynamically to the coffee.

Step 1: Create the Component Interface

We start by defining an interface ICoffee that declares the methods GetDescription

and GetCost . This interface will be implemented by both the base coffee class and
the decorators, ensuring they all provide a description and cost of the coffee.

public interface ICoffee


{
string GetDescription();

https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 2/13
19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

double GetCost();
}

Step 2: Implement Concrete Component

Next, we create the SimpleCoffee class that implements the ICoffee interface. This
class provides the basic functionality for a simple coffee, returning a description
and the base cost of the coffee.

public class SimpleCoffee : ICoffee


{
public string GetDescription()
{
return "Simple Coffee";
}

public double GetCost()


{
return 2.00;
}
}

Step 3: Create the Decorator Abstract Class

We then define an abstract class CoffeeDecorator that also implements the ICoffee

interface. This class holds a reference to an ICoffee object and delegates the
GetDescription and GetCost methods to the wrapped object. It serves as the base
class for all concrete decorators.

public abstract class CoffeeDecorator : ICoffee


{
protected ICoffee _coffee;

public CoffeeDecorator(ICoffee coffee)


{
_coffee = coffee;
}

public virtual string GetDescription()


{
return _coffee.GetDescription();
https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 3/13
19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

public virtual double GetCost()


{
return _coffee.GetCost();
}
}

Step 4: Implement Concrete Decorators

After that, we create concrete decorator classes like MilkDecorator , SugarDecorator ,

and WhipDecorator that extend CoffeeDecorator . Each of these classes adds its own
behavior to the GetDescription and GetCost methods, augmenting the wrapped
coffee object with additional properties and cost.

public class MilkDecorator : CoffeeDecorator


{
public MilkDecorator(ICoffee coffee) : base(coffee) { }

public override string GetDescription()


{
return base.GetDescription() + ", Milk";
}

public override double GetCost()


{
return base.GetCost() + 0.50;
}
}

public class SugarDecorator : CoffeeDecorator


{
public SugarDecorator(ICoffee coffee) : base(coffee) { }

public override string GetDescription()


{
return base.GetDescription() + ", Sugar";
}

public override double GetCost()


{
return base.GetCost() + 0.25;
}
}

public class WhipDecorator : CoffeeDecorator


{
https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 4/13
19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

public WhipDecorator(ICoffee coffee) : base(coffee) { }

public override string GetDescription()


{
return base.GetDescription() + ", Whip";
}

public override double GetCost()


{
return base.GetCost() + 0.75;
}
}

Step 5: Use the Decorator in Client Code

Finally, in the client code, we demonstrate how to use the decorators to dynamically
add behavior to the coffee object. We start with a SimpleCoffee and wrap it with
various decorators to add milk, sugar, and whipped cream, displaying the updated
description and cost after each addition. This illustrates the flexibility and
extensibility provided by the Decorator Pattern.

class Program
{
static void Main(string[] args)
{
ICoffee coffee = new SimpleCoffee();
Console.WriteLine($"{coffee.GetDescription()} : ${coffee.GetCost()}");

coffee = new MilkDecorator(coffee);


Console.WriteLine($"{coffee.GetDescription()} : ${coffee.GetCost()}");

coffee = new SugarDecorator(coffee);


Console.WriteLine($"{coffee.GetDescription()} : ${coffee.GetCost()}");

coffee = new WhipDecorator(coffee);


Console.WriteLine($"{coffee.GetDescription()} : ${coffee.GetCost()}");
}
}

Conclusion

https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 5/13
19/12/2024, 16:05 Design Patterns in C# Part 3: Enhancing Functionality with the Decorator Pattern | by João Melo | Medium

In this post, we’ve explored the Decorator Pattern, a powerful tool for dynamically
adding behavior to objects without modifying their structure. By using decorator
classes to wrap concrete components, we can enhance the functionality of objects in
a flexible and reusable manner. We’ve demonstrated this with a coffee shop
example, where customers can customize their coffee with various condiments like
milk, sugar, and whipped cream.

In the next post of this series, we will explore the Observer Pattern and discover
how it can further improve your code’s flexibility and maintainability.

Black coffee, no sugar, please.

Net Core C Sharp Programming Design Patterns Decorator Pattern

Backend Development

Follow

Written by João Melo


80 Followers · 6 Following

Software engineer, specializing in backend development with the C# language and the .NET Core.

https://medium.com/@joaopedrosmelo/design-patterns-in-c-part-3-enhancing-functionality-with-the-decorator-pattern-4750343e6f63 6/13

You might also like