Decorator Pattern – Streams in .NET

Decorator Pattern – Streams in .NET

Content originally published on my old blog in 2012.

The Decorator Pattern allows to attach additional responsibilities to an object dynamically. It is an alternative to subclassing for extending?behaviour.

Instead of creating a silly example of usage I decided to rely on one of the best example of implementation that is already available in the .NET Framework: the Streams.

The following class diagram is a restricted view of the Streams hierarchy in .NET:

No alt text provided for this image

Recognising the pattern is usually quite simple. When you see an object that inherit from a base class (Stream) and at the same time has a constructor that accept an element of the same base class (Stream), you?probably?came across to a Decorator.

The idea is that you can create an object that wraps an another object (of the same type) in order to provide new functionalities and the resulting object can be wrapped again creating a chain of objects that together provide a combination of functionalities. The beauty is that any single object is unaware that it is wrapped and this allows to create any combinations of them at runtime. If you consider the alternative of creating a single class for each combination of functionalities, the flexibility you get with the Decorator pattern is immense.

In the previous diagram there are three Decorators:

  • BufferedStream
  • CryptoStream
  • GZipStream

But what about the others classes?

FileStream, MemoryStream, NetworkStream does not have a constructor that takes a Stream. They simply are Components and not Decorators. This means that these objects can only be wrapped and cannot wrap other objects. These objects represent the end of the chain.

Yes, it seems quite complicated but it is not. Let’s make a concrete example.

Problem

Create a TCP client that allows you to send a message over the network to a TCP server. Before sending, the message will be buffered, compressed and then ciphered. The server will do the opposite operations in order to receive the message correctly.

Streams represents the best way to implement this scenario.

Solution

This is the code that creates a?TCP client and send the message over the network:

No alt text provided for this image

From the example, it should be easy to figure out how the wrapping process works. Wrapping is the way to add functionality in a dynamic way. If you don’t want to compress the data, you can simply remove the gzipStream wrapper. In addition, you can also change the order in which you want to execute the operations, simply wrapping in a different order. The decorator pattern provides you this flexibility.

The server side code is symmetric except that I decided to write the output to a file instead, using a FileStream.

No alt text provided for this image

Just for completeness this is the entry point of the program:

No alt text provided for this image

When you run the program the client send the message, the server receives and saves the message in a file that will be opened at the end.

No alt text provided for this image

The main Object Oriented Design principle respected by the decorator pattern is the?Open/Close Principle.

Software entities should be open for extension, but closed for modification.

What? How can you extend the system without changing it?

You can create a completely new class that inherit from Stream and add it into the chain in any position you want.

The streams hierarchy provided by .NET is open for extension but you don’t need to change the code of the framework to do this (it is closed for modification).

Roohollah Jafari

Senior Software Engineer( C# | GO | .Net | JS | React | Microservices | Blockchain)

1 年

The Decorator Pattern allows Us to add or modify the behavior of an object dynamically at runtime, without changing the original object. It is useful when we need to add new features or behaviors to an object without modifying its existing code. ?? ??

回复

要查看或添加评论,请登录

Andrea Angella的更多文章

  • 15 reasons why you should learn C# in 2024

    15 reasons why you should learn C# in 2024

    Why you should learn C#? This is the question I want to answer in this article. I am Andrea, a Microsoft MVP, Technical…

    8 条评论
  • The importance of defining performance goals

    The importance of defining performance goals

    This post was originally created in the Productive C# blog in 2016. Let’s start from some questions: Is you application…

  • The Singleton Pattern in .NET – Avoid it if you can!

    The Singleton Pattern in .NET – Avoid it if you can!

    This post was originally created in the Productive C# blog in 2012. The Singleton Pattern ensures a class has only one…

    3 条评论
  • Factory Method Pattern in .NET

    Factory Method Pattern in .NET

    This post was originally written on the Productive C# blog in 2012. There is a little bit of confusion around this…

  • The Command Pattern in .NET

    The Command Pattern in .NET

    The post was originally written on the Productive C# blog in 2012. The Command Pattern encapsulates a request as an…

    4 条评论
  • The Adapter Pattern in .NET

    The Adapter Pattern in .NET

    This post was originally written in the Productive C# blog in 2012. The Adapter Pattern converts the interface of a…

    2 条评论
  • The Facade Pattern in .NET

    The Facade Pattern in .NET

    This post was originally written on the Productiove C# blog in 2012. The Facade Pattern provides a unified interface to…

  • The Template Method Pattern in .NET

    The Template Method Pattern in .NET

    This post was originally written in the Productive C# blog in 2013. The Template Method Pattern defines the skeleton of…

    1 条评论
  • The Iterator Pattern in .NET

    The Iterator Pattern in .NET

    This post was originally written in the Productive C# blog in 2013. The Iterator Pattern provides a way to access the…

    1 条评论
  • Value Types and Reference Types in C#

    Value Types and Reference Types in C#

    This post was originally published on the Productive C# blog in 2019. Learn about the difference between value types…

社区洞察

其他会员也浏览了