Singleton Design Pattern C#

Ensure a class only has one instance, and provide a global point of access to it.

namespace TestSingleton
{
    class Program
    {
        static void Main(string[] args)
        {
            Logger logger1 = Logger.GetInstance();
            Logger logger2 = Logger.GetInstance();

            logger1.WriteMessage("This is a message from logger1");
            logger2.WriteMessage("This is a message from logger2");

            //This verifies that there is only one instance was created.
            if (logger1 == logger2)
            {
                Console.WriteLine("Both objects are of the same instance");
            }

            Console.ReadKey();
        }
    }

    /// <summary>
    /// Singleton Class
    /// </summary>
    public sealed class Logger
    {
        //Private Constructor
        private Logger() { }

        //Private instance variable
        private static Logger _loggerInstance = null;

        private static readonly object _threadsafeLock = new object();

        //Method to get instance (With Multithreaded thread safety and Lazy Instantiation)
        public static Logger GetInstance()
        {
            if (_loggerInstance == null)
            {
                lock (_threadsafeLock)
                {
                    _loggerInstance = _loggerInstance ?? new Logger();
                }
            }

            return _loggerInstance;
        }

        /// <summary>
        /// Write message to console or text file based on the requirement.
        /// </summary>
        public void WriteMessage(string message)
        {
            Console.WriteLine(message);
        }
    }
}

Ouptut:
This is a message from logger1
This is a message from logger2
Both objects are of the same instance

Abstract Factory Design Pattern C#

Abstract Factory offers the interface for creating a family of related objects, without explicitly specifying their classes.

AbstractFactory

Florist:

    /// <summary>
    /// Product A
    /// </summary>
    public interface IFlorist { void DecorateFlowers(); }
    
    /// <summary>
    /// Product A1
    /// </summary>
    public class HighBudgetFlorist : IFlorist
    {
        public void DecorateFlowers()
        {
            Console.WriteLine("Florist: Thanks for choosing us to serve...");
        }
    }

    /// <summary>
    /// Product A1
    /// </summary>
    public class LowBudgetFlorist : IFlorist
    {
        public void DecorateFlowers()
        {
            Console.WriteLine("Florist: Thanks for giving us the chance to serve...");
        }
    }

Caterer:

    /// <summary>
    /// Product B
    /// </summary>
    public interface ICaterer { void ServeFood(); }

    /// <summary>
    /// Product B1
    /// </summary>
    public class HighBudgetCaterer : ICaterer
    {
        public void ServeFood()
        {
            Console.WriteLine("Caterer: Thanks for choosing us to serve...");
        }
    }

    /// <summary>
    /// Product B2
    /// </summary>
    public class LowBudgetCaterer : ICaterer
    {
        public void ServeFood()
        {
            Console.WriteLine("Caterer: Thanks for giving us the chance to serve...");
        }
    }

EventOrganiser:

    /// <summary>
    /// Abstract Factory
    /// </summary>
    public interface IEventOrganiser
    {
        IFlorist GetFlorist();
        ICaterer GetCaterer();
    }

    /// <summary>
    /// Concrete factory 1
    /// </summary>
    public class HighBudetEventOrganiser : IEventOrganiser
    {
        public IFlorist GetFlorist()
        {
            return new HighBudgetFlorist();
        }

        public ICaterer GetCaterer()
        {
            return new HighBudgetCaterer();
        }
    }

    /// <summary>
    /// Concrete factory 2
    /// </summary>
    public class LowBudetEventOrganiser : IEventOrganiser
    {
        public IFlorist GetFlorist()
        {
            return new LowBudgetFlorist();
        }

        public ICaterer GetCaterer()
        {
            return new LowBudgetCaterer();
        }
    }

Interacting Client:

    /// <summary>
    /// Interacting Client
    /// </summary>
    public class EventManagementFirm
    {
        IEventOrganiser eventOrganiser;
        public EventManagementFirm(IEventOrganiser _eventOrganiser)
        {
            this.eventOrganiser = _eventOrganiser;
        }

        public void OganiseEvent()
        {
            IFlorist florist = eventOrganiser.GetFlorist();
            ICaterer caterer = eventOrganiser.GetCaterer();

            florist.DecorateFlowers();
            caterer.ServeFood();
        }
    }

Main Method:

static void Main(string[] args)
        {
            IEventOrganiser highProfileEvent = new HighBudetEventOrganiser();   //or LowBudetEventOrganiser
            EventManagementFirm eventManager = new EventManagementFirm(highProfileEvent);
            eventManager.OganiseEvent();
        }

Output:
AbstractFactoryOutput

Factory Method Design Pattern C#

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
FactoryMethodExample

namespace TestFactoryMethod
{
    class Program
    {
        static void Main(string[] args)
        {
            CarFactory carFactory = new SwiftCarFactory();
            ICar car = carFactory.GetCar();
            Console.ReadKey();
        }
    }

    /// <summary>
    /// Product
    /// </summary>
    public interface ICar
    {
        void BuildCar();
    }

    /// <summary>
    /// Concrete Product1
    /// </summary>
    public class SwiftCar : ICar
    {
        public SwiftCar()
        {
            Console.WriteLine("Swift car: Initialized...");
        }

        public void BuildCar()
        {
            Console.WriteLine("Swift car: Building...");
        }

        public void RunSwiftCarQualityCheck()
        {
            Console.WriteLine("Swift car: Quality Check is Successful...");
        }
    }

    /// <summary>
    /// Concrete Product2
    /// </summary>
    public class AltoCar : ICar
    {
        public AltoCar()
        {
            Console.WriteLine("Alto car: Initializing...");
        }

        public void BuildCar()
        {
            Console.WriteLine("Alto car: Building...");
        }

        public void RunAltoCarQualityCheck()
        {
            Console.WriteLine("Alto car: Quality Check is Successful...");
        }
    }

    /// <summary>
    /// Creator
    /// </summary>
    public abstract class CarFactory
    {
        public ICar GetCar()
        {
            ICar car = this.CreateCar();
            return car;
        }

        public abstract ICar CreateCar();
    }

    /// <summary>
    /// Concrete Creator1
    /// </summary>
    public class SwiftCarFactory : CarFactory
    {
        public override ICar CreateCar()
        {
            SwiftCar car = new SwiftCar();
            car.BuildCar();
            car.RunSwiftCarQualityCheck();
            return car;
        }
    }

    /// <summary>
    /// Concrete Creator2
    /// </summary>
    public class AltoCarFactory : CarFactory
    {
        public override ICar CreateCar()
        {
            AltoCar car = new AltoCar();
            car.BuildCar();
            car.RunAltoCarQualityCheck();
            return car;
        }
    }
}

Output:
FactoryMethodOutput

Simple Factory Design Pattern C#

Creates objects without exposing the instantiation logic to the client. Refers to the newly created object through a common interface

SimpleFactory

namespace TestSimpleFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            OperatingSystemFactory osFactory = new OperatingSystemFactory();
            IOperatingSystem windows = osFactory.GetOperatingSytemByType(OperatingSystemType.Windows);
            windows.DisplayWelcomeMessage();
            Console.ReadKey();
        }

        public interface IOperatingSystem
        {
            void DisplayWelcomeMessage();
        }

        public class Windows : IOperatingSystem
        {
            public void DisplayWelcomeMessage()
            {
                Console.WriteLine("Welcome to Windows Operating System");
            }
        }

        public class Linux : IOperatingSystem
        {
            public void DisplayWelcomeMessage()
            {
                Console.WriteLine("Welcome to Linux Operating System");
            }
        }       

        /// <summary>
        /// SimpleFactory
        /// </summary>
        public class OperatingSystemFactory
        {
            public IOperatingSystem GetOperatingSytemByType(OperatingSystemType osType)
            {
                if (osType == OperatingSystemType.Windows)
                {
                    return new Windows();
                }
                else if (osType == OperatingSystemType.Linux)
                {
                    return new Linux();
                }                

                return null;
            }
        }

        public enum OperatingSystemType
        {
            Windows,
            Linux
        }
    }
}

Output:
SimpleFactoryOutput