Software Development Design Patterns Made Simple

Design patterns are like tried-and-true solutions to problems that pop up when writing computer programs. They help us create code that works well, is easy to change, and can handle big tasks. Let’s explore a few popular design patterns and see how to use them with C#.

Singleton Pattern

Imagine a particular class you only want to have one copy of. The Singleton pattern ensures there’s only one, giving you an easy way to get to it from anywhere in your code. This is super handy when sharing something like a settings manager or a connection to a database.

Here’s a simple example in C#:

public class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }
}

Factory Method Pattern

Sometimes, you want to make different types of objects but keep things organized. The Factory Method pattern helps you do that. It defines a plan for making objects in a class and lets subclasses decide exactly which type to create. This keeps your code flexible and clean.

Here’s a quick C# example:

public interface IProduct
{
    string GetName();
}

public class ConcreteProductA : IProduct
{
    public string GetName()
    {
        return "Product A";
    }
}

public class ConcreteProductB : IProduct
{
    public string GetName()
    {
        return "Product B";
    }
}

public abstract class ProductFactory
{
    public abstract IProduct CreateProduct();
}

public class ConcreteFactoryA : ProductFactory
{
    public override IProduct CreateProduct()
    {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB : ProductFactory
{
    public override IProduct CreateProduct()
    {
        return new ConcreteProductB();
    }
}

Observer Pattern

Imagine you have objects that need to know when something important happens to another object. The Observer pattern helps with that. It sets up a system where one object (the “subject”) can notify many others (the “observers”) when it changes. This is useful for creating things like event-driven systems or graphical user interfaces (GUIs).

Here’s an example using C#:

public interface IObserver
{
    void Update(string message);
}

public interface ISubject
{
    void Attach(IObserver observer);
    void Detach(IObserver observer);
    void Notify();
}

public class ConcreteSubject : ISubject
{
    private List<IObserver> _observers = new List<IObserver>();
    private string _state;

    public string State
    {
        get { return _state; }
        set
        {
            _state = value;
            Notify();
        }
    }

    public void Attach(IObserver observer)
    {
        _observers.Add(observer);
    }

    public void Detach(IObserver observer
    {
        _observers.Remove(observer);
    }

    public void Notify()
    {
        foreach (var observer in _observers)
        {
            observer.Update(_state);
        }
    }
}

public class ConcreteObserver : IObserver
{
    public void Update(string message)
    {
        Console.WriteLine($"Received update: {message}");
    }
}

These design patterns are like handy tools for software developers. They give us ways to solve common problems in a smart and organized way. Just remember, you don’t have to use them all the time – only when they fit the problem you’re trying to solve.

I’m Peter

I’ve spent my career building software and leading engineering teams. I started as a developer and architect, grew into engineering leadership, and today I serve as a Chief Technology Officer.

Here, I share practical insights on technology, leadership, and building high-performing teams.

Connect with me on LinkedIn.

Discover more from Peter Mourfield

Subscribe now to keep reading and get access to the full archive.

Continue reading