{"id":1551,"date":"2023-04-14T12:00:59","date_gmt":"2023-04-14T05:00:59","guid":{"rendered":"https:\/\/csharptutorial.net\/?page_id=1551"},"modified":"2023-04-14T14:34:42","modified_gmt":"2023-04-14T07:34:42","slug":"csharp-decorator-pattern","status":"publish","type":"page","link":"https:\/\/www.csharptutorial.net\/csharp-design-patterns\/csharp-decorator-pattern\/","title":{"rendered":"C# Decorator Pattern"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to use extend the behavior of an object dynamically without using inheritance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction to the C# Decorator pattern<\/h2>\n\n\n\n<p>The Decorator pattern is a structural pattern that allows you to extend or modify the behavior of an object without changing the original implementation of the object.<\/p>\n\n\n\n<p>The following UML diagram illustrates the Decorator pattern:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/csharp-decorator-pattern.svg\" alt=\"\" class=\"wp-image-1552\"\/><\/figure>\n<\/div>\n\n\n<p>The Decorator pattern consists of the following elements:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>Component<\/code><\/strong>: This is the interface that defines operations an object can perform. The <code>Component<\/code> can be an <a href=\"https:\/\/csharptutorial.net\/csharp-tutorial\/csharp-interface\/\">interface<\/a> or an <a href=\"https:\/\/csharptutorial.net\/csharp-tutorial\/csharp-abstract-class\/\">abstract class<\/a>. The <code>Component<\/code> defines an object that will be decorated.<\/li>\n\n\n\n<li><strong><code>ConcreteComponent<\/code><\/strong>: This is the class that implements the <code>Component<\/code> interface.<\/li>\n\n\n\n<li><strong><code>Decorator<\/code><\/strong>: This is an abstract class that implements the <code>Component<\/code> interface and contains a reference to the <code>Component<\/code> object.<\/li>\n\n\n\n<li><strong><code>ConcreteDecorator<\/code><\/strong>: This is the class that extends the <code>Decorator<\/code> class and adds additional behavior to the <code>Component<\/code> object.<\/li>\n<\/ul>\n\n\n\n<p>In this diagram, the <code>Decorator<\/code> class inherits from the <code>Component<\/code>. But it uses inheritance to achieve <em>type matching<\/em> only, not to reuse the functionality of the <code>Component<\/code>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">C# Decorator pattern example<\/h2>\n\n\n\n<p>Let&#8217;s take an example to understand how the Decorator pattern works.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Developing a program that calls an API<\/h3>\n\n\n\n<p>Suppose you need to develop a program that calls the API from the following URL:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">https:<span class=\"hljs-comment\">\/\/jsonplaceholder.typicode.com\/posts\/1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The API returns a JSON object with the four fields <code>userId<\/code>, <code>id<\/code>, <code>title<\/code>, and <code>body<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">{\n  <span class=\"hljs-string\">\"userId\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n  <span class=\"hljs-string\">\"id\"<\/span>: <span class=\"hljs-number\">1<\/span>,\n  <span class=\"hljs-string\">\"title\"<\/span>: <span class=\"hljs-string\">\"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\"<\/span>,\n  <span class=\"hljs-string\">\"body\"<\/span>: <span class=\"hljs-string\">\"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following shows the steps for creating the program that calls the above API endpoint:<\/p>\n\n\n\n<p>First, create a <code>Post<\/code> class that has the four corresponding fields:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Post<\/span>\n{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> UserId { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> Id { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>;  }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Title  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Body  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">override<\/span> <span class=\"hljs-keyword\">string<\/span> <span class=\"hljs-title\">ToString<\/span>(<span class=\"hljs-params\"><\/span>)<\/span> =&gt; <span class=\"hljs-string\">$\"<span class=\"hljs-subst\">{Id}<\/span> - <span class=\"hljs-subst\">{Title}<\/span>\"<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>Post<\/code> class, the <code>ToString()<\/code> method returns a string that consists of the <code>Id<\/code> and <code>Title<\/code> of the <code>Post<\/code>.<\/p>\n\n\n\n<p>Second, create an interface called <code>IPostService<\/code> that has one method <code><code>GetPost<\/code><\/code>. The <code><code>GetPost<\/code><\/code> method gets a post by an id and returns a <code>Post<\/code> object:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IPostService<\/span>\n{\n    Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, create a <code>PostService<\/code> class that implements the <code>IPostService<\/code> interface:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostService<\/span> : <span class=\"hljs-title\">IPostService<\/span>\n{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> HttpClient client;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostService<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n    {\n        client = <span class=\"hljs-keyword\">new<\/span> HttpClient();\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        <span class=\"hljs-keyword\">var<\/span> url = <span class=\"hljs-string\">$\"https:\/\/jsonplaceholder.typicode.com\/posts\/<span class=\"hljs-subst\">{postId}<\/span>\"<\/span>;\n        <span class=\"hljs-keyword\">var<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.GetAsync(url);\n\n        <span class=\"hljs-keyword\">if<\/span> (response.IsSuccessStatusCode)\n        {\n            <span class=\"hljs-keyword\">var<\/span> responseBody = <span class=\"hljs-keyword\">await<\/span> response.Content.ReadAsStringAsync();\n\n            <span class=\"hljs-keyword\">var<\/span> post = JsonSerializer.Deserialize&lt;Post?&gt;(\n                responseBody,\n                <span class=\"hljs-keyword\">new<\/span> JsonSerializerOptions { PropertyNameCaseInsensitive = <span class=\"hljs-literal\">true<\/span> }\n            );\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n        <span class=\"hljs-keyword\">else<\/span>\n        {\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> Exception(<span class=\"hljs-string\">$\"Error: <span class=\"hljs-subst\">{response.StatusCode}<\/span>\"<\/span>);\n        }\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>PostService<\/code> class, the <code>GetPost<\/code> method uses the <code>HttpClient<\/code> to call the API to get the JSON response, and deserializes it to the <code>Post<\/code> object using the <code>JsonSerializer<\/code>, and returns the <code>Post<\/code>. The method raises an exception if an error occurs.<\/p>\n\n\n\n<p>Finally, use the <code>PostService<\/code> class to call the API and display the <code>Post<\/code> to the console:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Program<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">Main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span>&#91;] args<\/span>)<\/span>\n    {\n        <span class=\"hljs-keyword\">var<\/span> postService = <span class=\"hljs-keyword\">new<\/span> PostService();\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postService.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception)\n        {\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n    }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Putting it all together.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">using<\/span> System.Text.Json;\n\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">Decorator<\/span>;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Post<\/span>\n{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> UserId { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> Id { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>;  }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Title  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Body  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">override<\/span> <span class=\"hljs-keyword\">string<\/span> <span class=\"hljs-title\">ToString<\/span>(<span class=\"hljs-params\"><\/span>)<\/span> =&gt; <span class=\"hljs-string\">$\"<span class=\"hljs-subst\">{Id}<\/span> - <span class=\"hljs-subst\">{Title}<\/span>\"<\/span>;\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IPostService<\/span>\n{\n    Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId);\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostService<\/span> : <span class=\"hljs-title\">IPostService<\/span>\n{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> HttpClient client;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostService<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n    {\n        client = <span class=\"hljs-keyword\">new<\/span> HttpClient();\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        <span class=\"hljs-keyword\">var<\/span> url = <span class=\"hljs-string\">$\"https:\/\/jsonplaceholder.typicode.com\/posts\/<span class=\"hljs-subst\">{postId}<\/span>\"<\/span>;\n        <span class=\"hljs-keyword\">var<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.GetAsync(url);\n\n        <span class=\"hljs-keyword\">if<\/span> (response.IsSuccessStatusCode)\n        {\n            <span class=\"hljs-keyword\">var<\/span> responseBody = <span class=\"hljs-keyword\">await<\/span> response.Content.ReadAsStringAsync();\n\n            <span class=\"hljs-keyword\">var<\/span> post = JsonSerializer.Deserialize&lt;Post?&gt;(\n                responseBody,\n                <span class=\"hljs-keyword\">new<\/span> JsonSerializerOptions { PropertyNameCaseInsensitive = <span class=\"hljs-literal\">true<\/span> }\n            );\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n        <span class=\"hljs-keyword\">else<\/span>\n        {\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> Exception(<span class=\"hljs-string\">$\"Error: <span class=\"hljs-subst\">{response.StatusCode}<\/span>\"<\/span>);\n        }\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Program<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">Main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span>&#91;] args<\/span>)<\/span>\n    {\n        <span class=\"hljs-keyword\">var<\/span> postService = <span class=\"hljs-keyword\">new<\/span> PostService();\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postService.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception)\n        {\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n    }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-number\">1<\/span> - sunt aut facere repellat provident occaecati excepturi optio reprehenderit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The program works as expected.<\/p>\n\n\n\n<p>Now, you receive a new requirement that you need to log the API call. To do that you can modify the <code>PostService<\/code> class.<\/p>\n\n\n\n<p>But, if you do so, you&#8217;ll violate the <a href=\"https:\/\/csharptutorial.net\/csharp-design-patterns\/csharp-single-responsibility-principle\/\">single responsibility principle<\/a>. The <code>PostService<\/code> class should be responsible for calling the API and returning a <code>Post<\/code>. And it should not handle the logging functionality.<\/p>\n\n\n\n<p>To meet the new requirements without changing the <code>PostService<\/code> class, you can use the Decorator pattern by extending the <code>PostService<\/code> object dynamically.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding a decorator object<\/h3>\n\n\n\n<p>We&#8217;ll define two new classes: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>PostServiceDecorator<\/code> class which serves as the <code>Decorator<\/code> class<\/li>\n\n\n\n<li><code>PostServiceLoggingDecorator<\/code> class which acts as the <code>ConcreteDecorator<\/code> class:<\/li>\n<\/ul>\n\n\n\n<p>Here&#8217;s the new UML diagram:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/csharp-decorator-pattern-logging.svg\" alt=\"C# decorator pattern - logging\" class=\"wp-image-1555\"\/><\/figure>\n<\/div>\n\n\n<p>Note that we don&#8217;t include the <code>Post<\/code> class in the diagram to focus more on the Decorator pattern.<\/p>\n\n\n\n<p>First, define a new <code>PostServiceDecorator<\/code> abstract class that implements the <code><code>IPostService<\/code><\/code> interface and has an <code><code>IPostService<\/code><\/code> instance:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">abstract<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostServiceDecorator<\/span> : <span class=\"hljs-title\">IPostService<\/span>\n{\n    <span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">readonly<\/span> IPostService postService;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostServiceDecorator<\/span>(<span class=\"hljs-params\">IPostService postService<\/span>)<\/span>\n    {\n        <span class=\"hljs-keyword\">this<\/span>.postService = postService;\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">abstract<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId);\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, define the <code>PostLoggingDecorator<\/code> class that implements the <code>PostServiceDecorator<\/code> class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostServiceLoggingDecorator<\/span> : <span class=\"hljs-title\">PostServiceDecorator<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostServiceLoggingDecorator<\/span>(<span class=\"hljs-params\">IPostService postService<\/span>)\n        : <span class=\"hljs-title\">base<\/span>(<span class=\"hljs-params\">postService<\/span>)<\/span> { }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-keyword\">override<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        Console.WriteLine(<span class=\"hljs-string\">$\"Calling the API to get the post with ID: <span class=\"hljs-subst\">{postId}<\/span>\"<\/span>);\n        <span class=\"hljs-keyword\">var<\/span> stopwatch = Stopwatch.StartNew();\n\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postService.GetPost(postId);\n            Console.WriteLine(<span class=\"hljs-string\">$\"It took <span class=\"hljs-subst\">{stopwatch.ElapsedMilliseconds}<\/span> ms to call the API\"<\/span>);\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception ex)\n        {\n            Console.WriteLine(<span class=\"hljs-string\">$\"GetPostAsync threw exception: <span class=\"hljs-subst\">{ex.Message}<\/span>\"<\/span>);\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n        <span class=\"hljs-keyword\">finally<\/span>\n        {\n            stopwatch.Stop();\n        }\n\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code><code>GetPost()<\/code><\/code> method of <code>PostServiceLoggingDecorator<\/code> calls the <code><code>GetPost()<\/code><\/code> method of the <code>IPostService<\/code> instance. It also uses the StopWatch object to measure the time for calling the API and logs some information to the console.<\/p>\n\n\n\n<p>In other words, the <code>GetPost()<\/code> method of the <code>PostServiceLoggingDecorator<\/code> class adds the logging functionality to the <code>GetPost()<\/code> method of the <code>IPostService<\/code> object. <\/p>\n\n\n\n<p>Third, modify the <code>Program<\/code> class to use the <code>PostLoggingDecorator<\/code> class:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Program<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">Main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span>&#91;] args<\/span>)<\/span>\n    {\n        IPostService postService = <span class=\"hljs-keyword\">new<\/span> PostService();\n        <span class=\"hljs-keyword\">var<\/span> postServiceLogging = <span class=\"hljs-keyword\">new<\/span> PostServiceLoggingDecorator(postService);\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postServiceLogging.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception)\n        {\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n    }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the <code>Main()<\/code> method, we create an instance of the <code>PostService<\/code> and pass it to the constructor of the <code>PostServiceLoggingDecorator<\/code>. <\/p>\n\n\n\n<p>The <code>PostLoggingDecorator<\/code> acts as a decorator for the <code><code>PostService<\/code><\/code> object by adding the logging functionality to the <code><code>PostService<\/code><\/code> object.<\/p>\n\n\n\n<p>Put it all together.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">using<\/span> System.Diagnostics;\n<span class=\"hljs-keyword\">using<\/span> System.Text.Json;\n\n<span class=\"hljs-keyword\">namespace<\/span> <span class=\"hljs-title\">Decorator<\/span>;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Post<\/span>\n{\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> UserId { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> Id { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>;  }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Title  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">string<\/span>? Body  { <span class=\"hljs-keyword\">get<\/span>; <span class=\"hljs-keyword\">set<\/span>; }\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">override<\/span> <span class=\"hljs-keyword\">string<\/span> <span class=\"hljs-title\">ToString<\/span>(<span class=\"hljs-params\"><\/span>)<\/span> =&gt; <span class=\"hljs-string\">$\"<span class=\"hljs-subst\">{Id}<\/span> - <span class=\"hljs-subst\">{Title}<\/span>\"<\/span>;\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">IPostService<\/span>\n{\n    Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId);\n}\n\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostService<\/span> : <span class=\"hljs-title\">IPostService<\/span>\n{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> HttpClient client;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostService<\/span>(<span class=\"hljs-params\"><\/span>)<\/span>\n    {\n        client = <span class=\"hljs-keyword\">new<\/span> HttpClient();\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        <span class=\"hljs-keyword\">var<\/span> url = <span class=\"hljs-string\">$\"https:\/\/jsonplaceholder.typicode.com\/posts\/<span class=\"hljs-subst\">{postId}<\/span>\"<\/span>;\n        <span class=\"hljs-keyword\">var<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.GetAsync(url);\n\n        <span class=\"hljs-keyword\">if<\/span> (response.IsSuccessStatusCode)\n        {\n            <span class=\"hljs-keyword\">var<\/span> responseBody = <span class=\"hljs-keyword\">await<\/span> response.Content.ReadAsStringAsync();\n\n            <span class=\"hljs-keyword\">var<\/span> post = JsonSerializer.Deserialize&lt;Post?&gt;(\n                responseBody,\n                <span class=\"hljs-keyword\">new<\/span> JsonSerializerOptions { PropertyNameCaseInsensitive = <span class=\"hljs-literal\">true<\/span> }\n            );\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n        <span class=\"hljs-keyword\">else<\/span>\n        {\n            <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> Exception(<span class=\"hljs-string\">$\"Error: <span class=\"hljs-subst\">{response.StatusCode}<\/span>\"<\/span>);\n        }\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">abstract<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostServiceDecorator<\/span> : <span class=\"hljs-title\">IPostService<\/span>\n{\n    <span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">readonly<\/span> IPostService postService;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostServiceDecorator<\/span>(<span class=\"hljs-params\">IPostService postService<\/span>)<\/span>\n    {\n        <span class=\"hljs-keyword\">this<\/span>.postService = postService;\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">abstract<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId);\n\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostServiceLoggingDecorator<\/span> : <span class=\"hljs-title\">PostServiceDecorator<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostServiceLoggingDecorator<\/span>(<span class=\"hljs-params\">IPostService postService<\/span>)\n        : <span class=\"hljs-title\">base<\/span>(<span class=\"hljs-params\">postService<\/span>)<\/span> { }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-keyword\">override<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        Console.WriteLine(<span class=\"hljs-string\">$\"Calling the API to get the post with ID: <span class=\"hljs-subst\">{postId}<\/span>\"<\/span>);\n        <span class=\"hljs-keyword\">var<\/span> stopwatch = Stopwatch.StartNew();\n\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postService.GetPost(postId);\n            Console.WriteLine(<span class=\"hljs-string\">$\"It took <span class=\"hljs-subst\">{stopwatch.ElapsedMilliseconds}<\/span> ms to call the API\"<\/span>);\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception ex)\n        {\n            Console.WriteLine(<span class=\"hljs-string\">$\"GetPostAsync threw exception: <span class=\"hljs-subst\">{ex.Message}<\/span>\"<\/span>);\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n        <span class=\"hljs-keyword\">finally<\/span>\n        {\n            stopwatch.Stop();\n        }\n\n    }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Program<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">Main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span>&#91;] args<\/span>)<\/span>\n    {\n        IPostService postService = <span class=\"hljs-keyword\">new<\/span> PostService();\n        <span class=\"hljs-keyword\">var<\/span> postServiceLogging = <span class=\"hljs-keyword\">new<\/span> PostServiceLoggingDecorator(postService);\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postServiceLogging.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception)\n        {\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n    }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, we start with the <code>PostService<\/code> object:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/PostService.svg\" alt=\"\" class=\"wp-image-1559\"\/><\/figure>\n<\/div>\n\n\n<p>And decorate it with the <code>PostServiceLoggingDecorator<\/code> object by adding the logging functionality:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/Csharp-decorator-pattern-PostServiceLoggingDecorator.svg\" alt=\"\" class=\"wp-image-1562\"\/><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\">Adding more decorator object<\/h3>\n\n\n\n<p>Suppose, you want to improve the performance of the <code>PostService<\/code> class by caching the result of the API call.<\/p>\n\n\n\n<p>For example, if a post with id 1 is requested for the first time, you can directly call the API and save it into a cache. But if the same post is requested again, you can retrieve the <code>Post<\/code> with id 1 from the cache instead of making a call to the API. <\/p>\n\n\n\n<p>To do this, you can add a new decorator class called <code>PostServiceCache<\/code> that perform caching:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/csharp-decorator-pattern-cache.svg\" alt=\"C# decorator pattern - cache\" class=\"wp-image-1556\"\/><\/figure>\n<\/div>\n\n\n<p>First, define the <code>PostServiceCacheDecorator<\/code> that extends the <code>PostServiceDecorator<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PostServiceCacheDecorator<\/span> : <span class=\"hljs-title\">PostServiceDecorator<\/span>\n{\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">readonly<\/span> Dictionary&lt;<span class=\"hljs-keyword\">int<\/span>, Post&gt; cache;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">PostServiceCacheDecorator<\/span>(<span class=\"hljs-params\">IPostService postService<\/span>) : <span class=\"hljs-title\">base<\/span>(<span class=\"hljs-params\">postService<\/span>)<\/span>\n    {\n        cache = <span class=\"hljs-keyword\">new<\/span> Dictionary&lt;<span class=\"hljs-keyword\">int<\/span>, Post&gt;();\n    }\n\n    <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-keyword\">override<\/span> Task&lt;Post?&gt; GetPost(<span class=\"hljs-keyword\">int<\/span> postId)\n    {\n        <span class=\"hljs-comment\">\/\/ get post from the cache<\/span>\n        <span class=\"hljs-keyword\">if<\/span> (cache.TryGetValue(postId, <span class=\"hljs-keyword\">out<\/span> <span class=\"hljs-keyword\">var<\/span> post))\n        {\n            <span class=\"hljs-comment\">\/\/ demo purpose <\/span>\n            Console.WriteLine(<span class=\"hljs-string\">$\"Getting the post with id <span class=\"hljs-subst\">{postId}<\/span> from the cache\"<\/span>);\n            <span class=\"hljs-keyword\">return<\/span> post;\n        }\n\n        <span class=\"hljs-comment\">\/\/ otherwise call the API<\/span>\n        post = <span class=\"hljs-keyword\">await<\/span> postService.GetPost(postId);\n        <span class=\"hljs-keyword\">if<\/span> (post != <span class=\"hljs-literal\">null<\/span>)\n        {\n            cache&#91;postId] = post;\n        }\n        <span class=\"hljs-keyword\">return<\/span> post;\n\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>PostServiceCacheDecorator<\/code> class has a member <code>cache<\/code> that serves as a cache. The type of the <code>cache<\/code> is <code>Dictionary&lt;int, Post><\/code> which allows you to look up <code>Post<\/code> by id.<\/p>\n\n\n\n<p>The <code><code>GetPost()<\/code><\/code> method of the <code>PostServiceCacheDecorator<\/code> class checks the cache for the requested id and returns the <code>Post<\/code> if it is already in the cache. Otherwise, it uses the <code><code>GetPost()<\/code><\/code> method of the <code>PostService<\/code> object to call the API and adds the result into the cache.<\/p>\n\n\n\n<p>Second, modify the <code>Program<\/code> to use the <code>PostServiceCacheDecorator<\/code> that caches the result of the API call if the user requests the same post again:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Program<\/span>\n{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">Main<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span>&#91;] args<\/span>)<\/span>\n    {\n        IPostService postService = <span class=\"hljs-keyword\">new<\/span> PostService();\n        <span class=\"hljs-keyword\">var<\/span> postServiceLogging = <span class=\"hljs-keyword\">new<\/span> PostServiceLoggingDecorator(postService);\n        <span class=\"hljs-keyword\">var<\/span> postServiceCache = <span class=\"hljs-keyword\">new<\/span> PostServiceCacheDecorator(postServiceLogging);\n        <span class=\"hljs-keyword\">try<\/span>\n        {\n            <span class=\"hljs-keyword\">var<\/span> post = <span class=\"hljs-keyword\">await<\/span> postServiceCache.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n\n            <span class=\"hljs-comment\">\/\/ request the same post second time<\/span>\n            Console.WriteLine(<span class=\"hljs-string\">\"Getting the same post again:\"<\/span>);\n            post = <span class=\"hljs-keyword\">await<\/span> postServiceCache.GetPost(<span class=\"hljs-number\">1<\/span>);\n            Console.WriteLine(post);\n        }\n        <span class=\"hljs-keyword\">catch<\/span> (Exception)\n        {\n            <span class=\"hljs-keyword\">throw<\/span>;\n        }\n    }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Output:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">Calling the API to <span class=\"hljs-keyword\">get<\/span> the post with ID: <span class=\"hljs-number\">1<\/span>\nIt took <span class=\"hljs-number\">1698<\/span> ms to call the API\n<span class=\"hljs-number\">1<\/span> - sunt aut facere repellat provident occaecati excepturi optio reprehenderit\nGetting the same post again:\nGetting the post with id <span class=\"hljs-number\">1<\/span> <span class=\"hljs-keyword\">from<\/span> the cache\n<span class=\"hljs-number\">1<\/span> - sunt aut facere repellat provident occaecati excepturi optio reprehenderit<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows that the second call to the <code>GetPost<\/code> method does not call the API but gets the result from the cache.<\/p>\n\n\n\n<p>In this example, the PostServiceLoggingDecorator decorates the PostService and the PotServiceCacheDecorator decorates the PostServiceLoggingDecorator class.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/CSharp-decorator-pattern-PostServiceCacheDecorator.svg\" alt=\"C# decorator pattern - PostServiceCacheDecorator\" class=\"wp-image-1561\"\/><\/figure>\n<\/div>\n\n\n<p>If you want to, you can add more decorator classes and they decorate each other to add more functionality to the decorated objects. <\/p>\n\n\n\n<p>Also, you can mix and match the decorator based on the requirements. This makes your code more flexible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Decorator pattern in .NET<\/h2>\n\n\n\n<p>.NET uses the decorator pattern in some libraries. For example, the <code>BufferedStream<\/code>, <code>GZipStream<\/code>, and <code>CryptoStream<\/code> classes are the decorators of the <code>Stream<\/code> class. The <code>FileStream<\/code>, <code>MemoryStream<\/code>, and <code>NetworkStream<\/code> are concrete <code>Stream<\/code> classes.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" src=\"https:\/\/csharptutorial.net\/wp-content\/uploads\/2023\/04\/CSharp-Design-pattern-example-in-NET.svg\" alt=\"\" class=\"wp-image-1569\"\/><\/figure>\n<\/div>\n\n\n<p>Note that the <code>Stream<\/code> and <code>FileStream<\/code> classes have more methods that the ones listed on the diagram. We put out the <code>Read<\/code> and <code>Write<\/code> method only for simplification purposes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use the C# decorator pattern to extend the behavior of an object dynamically at runtime without using inheritance.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"1551\"\n\t\t\t\tdata-post-url=\"https:\/\/www.csharptutorial.net\/csharp-design-patterns\/csharp-decorator-pattern\/\"\n\t\t\t\tdata-post-title=\"C# Decorator Pattern\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"1551\"\n\t\t\t\tdata-post-url=\"https:\/\/www.csharptutorial.net\/csharp-design-patterns\/csharp-decorator-pattern\/\"\n\t\t\t\tdata-post-title=\"C# Decorator Pattern\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to use extend the behavior of an object dynamically without using inheritance.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1441,"menu_order":16,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-1551","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/1551","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/comments?post=1551"}],"version-history":[{"count":5,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/1551\/revisions"}],"predecessor-version":[{"id":1571,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/1551\/revisions\/1571"}],"up":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/1441"}],"wp:attachment":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/media?parent=1551"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}