Understanding the Decorator Pattern Through a MacBook Customization Example in C#

The Decorator Pattern is a powerful structural design pattern that enables adding new behavior to objects dynamically without modifying their original code. This is especially useful when you want to extend functionalities without creating a complex hierarchy of subclasses. In this article, I’ll explain the Decorator Pattern using a practical example: customizing a MacBook with different configurations like upgrading RAM, SSD, and adding AppleCare protection. What is the Decorator Pattern? The Decorator Pattern allows you to "wrap" an object with additional features or responsibilities at runtime. Instead of creating many subclasses for every possible combination, decorators let you compose behaviors dynamically by stacking objects. The MacBook Example Overview We start with a base MacBook configuration: 16GB RAM 256GB SSD Base price Using decorators, we can: Upgrade RAM to 24GB Upgrade SSD to 512GB Add AppleCare protection Each decorator modifies the price and relevant specs accordingly. Core Components The Interface IMacBook Defines the contract with methods like: GetDescription() GetPrice() GetRamSize() GetSSDSize() The Base Class BaseMacBook16Ram256SSD Implements IMacBook and represents the default MacBook configuration. The Abstract Decorator MackBookDecorator This class implements IMacBook and wraps another IMacBook instance. It delegates calls to the wrapped instance but can be extended to add or override behavior. Concrete Decorators MacBookWithAppleCare: Adds AppleCare price and description. MacBook512SSD: Adds extra SSD storage and price. MacBook24RAM: Adds extra RAM and price. How to Use It You can compose different MacBook configurations by wrapping the base object with decorators like this: IMacBook macBook16Ram256SSD = new BaseMacBook16Ram256SSD(); IMacBook macBook16Ram512Sdd = new MacBook512SSD(macBook16Ram256SSD); IMacBook macBook24Ram512Sdd = new MacBook24RAM(macBook16Ram512Sdd); IMacBook macBook24Ram512SddWithAppleCare = new MacBookWithAppleCare(macBook24Ram512Sdd); Console.WriteLine(macBook16Ram256SSD); Console.WriteLine(macBook16Ram512Sdd); Console.WriteLine(macBook24Ram512Sdd); Console.WriteLine(macBook24Ram512SddWithAppleCare); Each line creates a new configuration by decorating the previous one. Why Use the Decorator Pattern? Open/Closed Principle: Extend object behavior without changing existing code. Flexibility: Combine decorators in any order to create new behaviors. Avoids Class Explosion: No need to create a subclass for every combination. Real-World Applications The Decorator Pattern is widely used in software development: Adding scrollbars or borders in UI frameworks. Enhancing functionalities like logging, caching, or security by wrapping services. Customizing product configurations dynamically, just like our MacBook example. Conclusion The Decorator Pattern is an elegant way to add responsibilities to objects dynamically and flexibly. Using this pattern, you keep your codebase maintainable and avoid unnecessary class proliferation. You can find the full source code for this example on my GitHub repository: DecoratorPattern

Jun 10, 2025 - 09:20
 0
Understanding the Decorator Pattern Through a MacBook Customization Example in C#

The Decorator Pattern is a powerful structural design pattern that enables adding new behavior to objects dynamically without modifying their original code. This is especially useful when you want to extend functionalities without creating a complex hierarchy of subclasses.

In this article, I’ll explain the Decorator Pattern using a practical example: customizing a MacBook with different configurations like upgrading RAM, SSD, and adding AppleCare protection.

What is the Decorator Pattern?

The Decorator Pattern allows you to "wrap" an object with additional features or responsibilities at runtime. Instead of creating many subclasses for every possible combination, decorators let you compose behaviors dynamically by stacking objects.

The MacBook Example Overview

We start with a base MacBook configuration:

  • 16GB RAM
  • 256GB SSD
  • Base price
  • Using decorators, we can:
  • Upgrade RAM to 24GB
  • Upgrade SSD to 512GB
  • Add AppleCare protection

Each decorator modifies the price and relevant specs accordingly.

Core Components

The Interface IMacBook
Defines the contract with methods like:

  • GetDescription()
  • GetPrice()
  • GetRamSize()
  • GetSSDSize()

The Base Class BaseMacBook16Ram256SSD

Implements IMacBook and represents the default MacBook configuration.

The Abstract Decorator MackBookDecorator

This class implements IMacBook and wraps another IMacBook instance. It delegates calls to the wrapped instance but can be extended to add or override behavior.

Concrete Decorators

  • MacBookWithAppleCare: Adds AppleCare price and description.
  • MacBook512SSD: Adds extra SSD storage and price.
  • MacBook24RAM: Adds extra RAM and price.

How to Use It

You can compose different MacBook configurations by wrapping the base object with decorators like this:

IMacBook macBook16Ram256SSD = new BaseMacBook16Ram256SSD();
IMacBook macBook16Ram512Sdd = new MacBook512SSD(macBook16Ram256SSD);
IMacBook macBook24Ram512Sdd = new MacBook24RAM(macBook16Ram512Sdd);
IMacBook macBook24Ram512SddWithAppleCare = new MacBookWithAppleCare(macBook24Ram512Sdd);

Console.WriteLine(macBook16Ram256SSD);
Console.WriteLine(macBook16Ram512Sdd);
Console.WriteLine(macBook24Ram512Sdd);
Console.WriteLine(macBook24Ram512SddWithAppleCare);

Each line creates a new configuration by decorating the previous one.

Why Use the Decorator Pattern?

  • Open/Closed Principle: Extend object behavior without changing existing code.
  • Flexibility: Combine decorators in any order to create new behaviors.
  • Avoids Class Explosion: No need to create a subclass for every combination.

Real-World Applications

The Decorator Pattern is widely used in software development:

  • Adding scrollbars or borders in UI frameworks.
  • Enhancing functionalities like logging, caching, or security by wrapping services.
  • Customizing product configurations dynamically, just like our MacBook example.

Conclusion

The Decorator Pattern is an elegant way to add responsibilities to objects dynamically and flexibly. Using this pattern, you keep your codebase maintainable and avoid unnecessary class proliferation.

You can find the full source code for this example on my GitHub repository: DecoratorPattern