Category: designPatterns

Pattern: Factory

Description

A factory is a function or method that returns objects of a varying prototype or class from some method call, which is assumed to be new

Example in .NET :

Factory

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Internal;
using System.Data.Common;
using System.Globalization;
using System.Net;
using System.Web.Mvc;
 
namespace Factory;
internal class FactoryDemo
{
    public static void DemoWebRequest()
    {
        HttpWebRequest hwr = (HttpWebRequest)WebRequest.Create("http://www.yahoo.com");
 
    }
    public static void DemoConvert()
    {
        string value = "1,500";
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
 
        Console.WriteLine(Convert.ToDouble(value));
 
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
        Console.WriteLine(Convert.ToDouble(value));
 
    }
    static void RegisterControllerFactory()
    {
        ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
    }
}
 
//default controller factory is a factory of controllers
class MyControllerFactory : System.Web.Mvc.DefaultControllerFactory
{
 
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        if (controllerName == "andrei")
            return null;//maybe controller not found
 
        return base.CreateController(requestContext, controllerName);
    }
}
    

Learn More

Wikipedia

Homework

having multiple types of drinks( water, tea, coffee) with an IDrink interface create a factory method ( with a parameter ) to create a drink

Pattern: Prototype

Description

It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects

Example in .NET :

ICloneable

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System; 
namespace Prototype;
class Parent : ICloneable
{
    public int Age { get; set; }
    public Child MyChild { get; set; }
 
    public object Clone()
    {
        //TODO: serialize + unserialize
        //with System.Text.Json.JsonSerializer
 
        var p = ShallowClone();
        //TODO: clone the child
        var c = new Child();
        c.Age = this.MyChild.Age;
 
        p.MyChild = c;
        return p;
    }
 
    public Parent ShallowClone()
    {
        return this.MemberwiseClone() as Parent;
    }
}

Learn More

Wikipedia

Homework

Imagine that you have a cow farm and you want to create a new cow. Implement a prototype that will allow you to clone a cow. The cow should have a name and a weight

Pattern: Singleton

Description

Singleton pattern restricts the instantiation of a class to one object. It is used when you want to have one instance of a class that is shared across the application.

Example in .NET :

Singleton

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Data.OleDb;
 
namespace Singleton;
/// <summary>
///
///sealed class Singleton
///{
///    private Singleton() { }
///    public static readonly Singleton Instance = new Singleton();
///}
///
/// </summary>
internal class SingletonDemo
{
    public static void GetFactory()
    {
        //cannot do new
        //OleDbFactory factory=new OleDbFactory();
        //get singleton instance
        OleDbFactory factory = OleDbFactory.Instance;
    }
}

Learn More

Wikipedia

Homework

Implement a singleton that will allow you to create a single instance of a logger that logs to a file and to a console.

Pattern: Strategy

Description

Strategy pattern allows a client to choose from a family of algorithms at runtime. It is used when the client expects to have multiple algorithms and wants to choose one of them at runtime.

Example in .NET :

Strategy

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System;
using System.Collections.Generic;
 
namespace Strategy;
internal class StrategyDemo
{
    public static void SortWithDifferentStrategies()
    {
        List<int> al = new ();
        al.Add(102);
        al.Add(201);
        //sort ascending
        al.Sort((x, y) =&gt; x.CompareTo(y));
 
        for (int i = 0; i &lt; al.Count; i++)
        {
            Console.WriteLine(al[i]);
        }
 
        Console.WriteLine("---------------");
 
        //sort descending
        al.Sort((y, x) =&gt; x.CompareTo(y));
        for (int i = 0; i &lt; al.Count; i++)
        {
            Console.WriteLine(al[i]);
        }
        Console.WriteLine("---------------");
        //sort custom
        al.Sort((x, y) =&gt; LastDigit(x).CompareTo(LastDigit(y)));
        for (int i = 0; i &lt; al.Count; i++)
        {
            Console.WriteLine(al[i]);
        }
 
        var array = al.FindAll(it =&gt; it &gt; 10);
 
 
    }
 
    static int LastDigit(int x)
    {
        return x % 10;
    }
 
}

Learn More

Wikipedia

Homework

Image you want to serialize classes to XML,JSON and CSV . Implement a strategy that will allow you to choose between XML , JSON and CSV serialization at runtime.

Pattern: Visitor

Description

Visitor pattern is a way of separating an algorithm from an object structure on which it operates. A practical result of this separation is the ability to add new operations to existing object structures without modifying the structures.

Example in .NET :

Visitor

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
 
namespace Visitor;
internal class VisitorDemo
{
    public static void VisitMethods()
    {
        var Code = @"""
using System;
namespace Test1
{
    class Program
    {
        static void Main(string[] args)
        {
              var dt=DateTime.Now;
              Console.WriteLine(dt);
        }
     }
}
 
""";
        var tree = CSharpSyntaxTree.ParseText(Code);
 
        var node = tree.GetRoot();
 
        MethodVisiting LG = new MethodVisiting();
        //start visiting
        var sn = LG.Visit(node);
 
    }
}
public class MethodVisiting : CSharpSyntaxRewriter
{
    public override SyntaxNode? VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        if (node.Body == null || node.Body.Statements.Count == 0)
            return base.VisitMethodDeclaration(node);
 
        var parent = node.Parent as ClassDeclarationSyntax;
         
        if (parent == null)
            return base.VisitMethodDeclaration(node);
 
        var nameMethod = node.Identifier.Text;
        var nameClass = parent.Identifier.Text;
        Console.WriteLine($"visiting {nameMethod} from {nameClass}");
 
        return base.VisitMethodDeclaration(node);
 
    }
}

Learn More

Wikipedia

Homework

Implement a visitor that will allow you to calculate the total price of a shopping cart. The shopping cart should contain items with a price and a quantity.Visit every item and make the sum

Pattern: Adapter

Description

Adapter design pattern allows the interface of an existing class to be used as another interface.It is often used to make existing classes work with others without modifying their source code.

Examples in .NET :

SQLiteDataAdapter

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
namespace Adaptor;
internal class SQLiteDataAdapterDemo
{
    /// <summary>
    ///Adaptee  - Command
    ///Target  - DataTable
    ///Adapter  - SqlDataAdapter
    ///Target Method - Fill(Dataset instance)
    /// </summary>
    /// <returns></returns>
    public static async Task MainSqliteAdapterAsync()
    {
        var dataFormats = new DataTable();
        Console.WriteLine(dataFormats.Rows.Count);
        Console.WriteLine(dataFormats.Columns.Count);
        using (var con = new SQLiteConnection())
        {
            con.ConnectionString = "Data Source=CatalogRo.sqlite3";
            await con.OpenAsync();
            using (var cmd = new SQLiteCommand())
            {
                cmd.CommandText = "select * from Format";
                cmd.Connection = con;
                using (var adapt = new SQLiteDataAdapter(cmd))
                {
                    adapt.Fill(dataFormats);
                }
            }
 
        }
        Console.WriteLine(dataFormats.Rows.Count);
        Console.WriteLine(dataFormats.Columns.Count);
    }
}

EncodingAdapter

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace Adaptor;
internal class EncodingAdapterDemo
{
    /// <summary>
    ///Adaptee  - string
    ///Target  - bytes
    ///Adapter  - encoding
    ///Target Method - GetBytes
    /// </summary>
    public static void AdapterStringByte()
    {
        var url = "http://msprogrammer.serviciipeweb.ro";
        Encoding e = new ASCIIEncoding();
        var b = e.GetBytes(url);
 
        Console.WriteLine($"from {e.EncodingName} number bytes {b.Length}");
 
        e = new UTF32Encoding();
        b = e.GetBytes(url);
        Console.WriteLine($"from {e.EncodingName} number bytes {b.Length}");
 
    }
 
 
}

Learn More

Wikipedia

Homework

iPhone 7 does not have a headphone jack. Implement an adapter that will allow you to use your old headphones , that have jack, with the iPhone 7.

Pattern: Builder

Description

The intent of the Builder design pattern is to separate the construction of a complex object from its representation

Examples in .NET :

UriBuilder

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
namespace Builder;
static class UriBuilderDemo
{
    public static void UriMod()
    {
        //start example 1
        var b = new UriBuilder(uri);
        //changing part
        b.Scheme = "http";
        Console.WriteLine(b.Uri);
        //changing part
        b.Path = "2018/03/05/design-patterns-class/";
        Console.WriteLine(b.Uri);
        //end example 1
    }
}

SqlConnectionStringBuilder

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
namespace Builder;
internal class ConnectionStringDemo
{
    public static void ConnectionString()
    {
        //start example 2
        var build = new SqlConnectionStringBuilder();
        build.DataSource = ".";
        build.InitialCatalog = "MyDatabase";
        build.ConnectTimeout = 30;
        //here is the connection string built
        Console.WriteLine(build.ConnectionString);
        //end example 2
    }
}

Learn More

Wikipedia

Homework

Imagine that you have a logger that logs to a file and to a console. Implement a builder that will allow you to create a logger with different configurations. For example, you can set the log level, the log format, and the log destination.

Pattern: Iterator

Description

Iterator design pattern allows to traverse a container and access the container’s elements.

Example in .NET :

DirectoryEnumerable

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
namespace Iterator;
internal class DirectoryEnumerableDemo
{
    public static void DirectoryEnumerableFiles(int nrMaxFiles)
    {
        var count = 0;
        //what if we called Directory.GetFiles       
        foreach (var file in Directory.EnumerateFiles(@"c:\","*.*",SearchOption.AllDirectories))
        {
            count++;
            if (count > nrMaxFiles)
                break;
            Console.WriteLine(file);
        }
    }
}

Learn More

Wikipedia

Homework

With the Yield keyword implement a function that return an IEnumerable of generic int that will return the first 10 numbers of the Fibonacci sequence

Pattern: NullObject

Description

Instead of returning null , use an object which implements the expected interface, but whose method body is empty.

Examples in .NET :

EmptyFolder

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.IO;
 
namespace NullObject;
internal class EmptyFolderDemo
{
    public static void DemoWithCreateNewFolder()
    {
        //start example 1
        var env = Environment.CurrentDirectory;
        var guid = Guid.NewGuid().ToString("X");
        var fldEmpty = Path.Combine(env, guid);
        //create empty folder
        Directory.CreateDirectory(fldEmpty);
        var files= Directory.GetFiles(fldEmpty);
        Console.WriteLine($"files.Length:{files.Length}");
        //end example 1
         
    }
}

NullLogger

01
02
03
04
05
06
07
08
09
10
11
12
13
namespace NullObject;
internal class LogWithData
{
    ILogger _logger;
    public LogWithData(ILogger? logger=null)
    {
        _logger = logger ?? NullLogger.Instance;  
    }
    public void DoWork(string message)
    {
        _logger.LogInformation($"start work with {message}");
    }
}

Learn More

Wikipedia

Homework

When retrieving data( e.g. a Person with ID =-1 ) from a database , return a NullObject instead of null. How you will verify that the object is a NullObject?

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.