Implementing Creational Patterns

Tutorial 2 of 5

Implementing Creational Patterns

1. Introduction

In this tutorial, we will take a deep dive into the practical implementation of Creational Patterns in C#. We will focus on the Singleton and Factory patterns, providing examples and use cases for each.

By the end of this tutorial, you will be able to:
- Understand and implement the Singleton and Factory design patterns in C#
- Identify situations where these patterns can be beneficially applied
- Write clean and efficient C# code

Prerequisites:

  • Basic knowledge of C#
  • Familiarity with Object-Oriented Programming concepts

2. Step-by-Step Guide

Singleton Pattern

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. It is useful when exactly one object is needed to coordinate actions across the system.

public class Singleton
{
    private static Singleton instance;

    // Constructor is 'protected' to prevent instance creation through 'new Singleton()'
    protected Singleton() { }

    public static Singleton Instance
    {
        get
        {
            // Create a new instance if one doesn't exist.
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

Factory Pattern

The Factory pattern provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It's useful when a method returns one of several possible classes that share a common superclass.

public abstract class Animal
{
    public abstract string Speak();
}

public class Dog : Animal
{
    public override string Speak()
    {
        return "Woof!";
    }
}

public class Cat : Animal
{
    public override string Speak()
    {
        return "Meow!";
    }
}

public class AnimalFactory
{
    public Animal GetAnimal(string animalType) 
    {
        switch (animalType)
        {
            case "Dog":
                return new Dog();
            case "Cat":
                return new Cat();
            default:
                throw new Exception("Invalid animal type");
        }
    }
}

3. Code Examples

Singleton Pattern

public class Singleton
{
    private static Singleton instance;

    protected Singleton() { }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Singleton s1 = Singleton.Instance;
        Singleton s2 = Singleton.Instance;

        // Outputs: "True"
        Console.WriteLine(s1 == s2);
    }
}

Factory Pattern

class Program
{
    static void Main(string[] args)
    {
        AnimalFactory animalFactory = new AnimalFactory();

        Animal myDog = animalFactory.GetAnimal("Dog");
        Animal myCat = animalFactory.GetAnimal("Cat");

        // Outputs: "Woof!"
        Console.WriteLine(myDog.Speak());

        // Outputs: "Meow!"
        Console.WriteLine(myCat.Speak());
    }
}

4. Summary

In this tutorial, we have covered Singleton and Factory design patterns in C#. We learned how to implement these patterns and identified situations for their use.

For further learning, you can explore other Creational Patterns like the Prototype, Builder, and Abstract Factory patterns. Here are a few resources that might be helpful:
- Design Patterns in C#
- Gang of Four Design Patterns

5. Practice Exercises

  1. Exercise 1: Create a Singleton class for a Logger that can be used across different parts of a program.
  2. Exercise 2: Implement a Shape Factory that can create and return different shapes (like Circle, Square, Rectangle).
  3. Exercise 3: Modify the Animal Factory example to include more animals.

Solutions

  • Solutions can be found here. Remember, the key to learning is practice! Try to solve the exercises yourself before checking the solutions.