Decorator - Structural
Overview:
The Decorator Pattern in C# is a style maestro, letting you wrap and unwrap objects in layers of functionality without breaking a sweat. Let's explore this fashion-forward coding approach:
Implementation in C#:
In C#, the Decorator Pattern revolves around dynamically adding or modifying behavior of objects. Consider a Coffee class with decorators:
// Component interface
public interface ICoffee
{
string Brew();
}
// Concrete component
public class BasicCoffee : ICoffee
{
public string Brew() { return "Basic coffee brewed."; }
}
// Decorator
public abstract class CoffeeDecorator : ICoffee
{
protected ICoffee coffee;
public CoffeeDecorator(ICoffee coffee)
{
this.coffee = coffee;
}
public virtual string Brew()
{
return coffee.Brew();
}
}
// Concrete decorator
public class MilkDecorator : CoffeeDecorator
{
public MilkDecorator(ICoffee coffee) : base(coffee) { }
public override string Brew()
{
return $"{base.Brew()} + Milk added.";
}
}
Pros:
-
Flexible Extension: Dynamically adds or modifies functionality without altering the core class.
-
Easy Composition: Allows combining multiple decorators, creating versatile combinations.
-
Open/Closed Principle: Supports extension without modifying existing code.
Cons:
-
Complexity: Introducing multiple decorators may increase code complexity.
-
Learning Curve: Developers new to the pattern may need time to understand its structure.
When to Use and When Not:
-
Use: When you need to extend functionality in a flexible, composable way without modifying existing code.
-
Avoid: In scenarios where the system is simple, and extensions are unlikely or straightforward.
Usage in .NET Core Framework:
The Decorator Pattern is prevalent in the .NET Core framework, especially in the IO streams. Classes like FileStream, BufferedStream, and CryptoStream are examples of decorators that add functionality to the basic stream classes.
Real-Life Example:
Consider a scenario where you're reading and writing encrypted data to a file. Instead of modifying the existing FileStream, you can use a CryptoStream decorator to seamlessly add encryption functionality:
// Original file stream
var fileStream = new FileStream("secret.txt", FileMode.OpenOrCreate);
// Decorate with encryption
var encryptedStream = new CryptoStream(fileStream, new AesCryptoServiceProvider().CreateEncryptor(), CryptoStreamMode.Write);
// Now, use the encrypted stream for writing
using (var writer = new StreamWriter(encryptedStream))
{
writer.WriteLine("Top-secret message!");
}
Here, the CryptoStream decorates the original FileStream, adding encryption capabilities without altering the core file stream behavior.
In conclusion, the Decorator Pattern in C# is a design virtuoso, letting you layer functionality onto objects with grace. While it introduces a layer of complexity, the benefits of flexible extension and easy composition make it a stylish choice for crafting elegant and adaptable software. Its influence in the .NET Core framework, particularly in IO streams, exemplifies its timeless relevance in real-world scenarios where functionality layers harmonize to create software symphonies.
No files yet, migration hasn't completed yet!