> For the complete documentation index, see [llms.txt](https://huy312100.gitbook.io/software-development/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://huy312100.gitbook.io/software-development/design-pattern/use-cases.md).

# Use cases

1. **Singleton Pattern**:

* **Real-life Example**: Managing a configuration settings object for an application. There should only be one instance of the configuration settings to avoid inconsistencies.
* **Explanation**: Ensures a class has only one instance and provides a global point of access to it.

```csharp
public class ConfigurationManager
{
    private static ConfigurationManager _instance;
    private static readonly object _lock = new object();

    public string Setting { get; set; }

    private ConfigurationManager() { }

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

// Usage
ConfigurationManager.Instance.Setting = "Some setting";
Console.WriteLine(ConfigurationManager.Instance.Setting);

```

2. **Observer Pattern**:

* **Real-life Example**: Notification systems. When an event (like an email received) occurs, all the subscribers (such as different modules of an application) are notified and updated automatically.
* **Explanation**: Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

```csharp
using System;
using System.Collections.Generic;

// Subject Interface
public interface IEmailSubject
{
    void RegisterObserver(IEmailObserver observer);
    void RemoveObserver(IEmailObserver observer);
    void NotifyObservers();
}

// Observer Interface
public interface IEmailObserver
{
    void Update(string message);
}

// Concrete Subject
public class EmailServer : IEmailSubject
{
    private List<IEmailObserver> observers;
    private string emailMessage;

    public EmailServer()
    {
        observers = new List<IEmailObserver>();
    }

    public string EmailMessage
    {
        get { return emailMessage; }
        set
        {
            emailMessage = value;
            NotifyObservers();
        }
    }

    public void RegisterObserver(IEmailObserver observer)
    {
        observers.Add(observer);
    }

    public void RemoveObserver(IEmailObserver observer)
    {
        observers.Remove(observer);
    }

    public void NotifyObservers()
    {
        foreach (var observer in observers)
        {
            observer.Update(emailMessage);
        }
    }
}

// Concrete Observers
public class MobileApp : IEmailObserver
{
    public void Update(string message)
    {
        Console.WriteLine("Mobile App Notification: " + message);
    }
}

public class DesktopApp : IEmailObserver
{
    public void Update(string message)
    {
        Console.WriteLine("Desktop App Notification: " + message);
    }
}

public class WebApp : IEmailObserver
{
    public void Update(string message)
    {
        Console.WriteLine("Web App Notification: " + message);
    }
}

// Program
class Program
{
    static void Main()
    {
        // Create a subject
        EmailServer emailServer = new EmailServer();

        // Create observers
        IEmailObserver mobileApp = new MobileApp();
        IEmailObserver desktopApp = new DesktopApp();
        IEmailObserver webApp = new WebApp();

        // Register observers
        emailServer.RegisterObserver(mobileApp);
        emailServer.RegisterObserver(desktopApp);
        emailServer.RegisterObserver(webApp);

        // Change the state of the subject
        emailServer.EmailMessage = "New Email: 'Observer Design Pattern in C#'";

        // Remove an observer
        emailServer.RemoveObserver(desktopApp);

        // Change the state of the subject again
        emailServer.EmailMessage = "New Email: 'Advanced C# Programming'";
    }
}
```

3. **Factory Pattern**:

* **Real-life Example**: Creating objects in a banking application for different types of accounts (e.g., savings, checking). The factory method can return different types of accounts based on the input provided.
* **Explanation**: Defines an interface for creating an object, but lets subclasses alter the type of objects that will be created.

```csharp
using System;

// Product: Account interface
public interface IAccount
{
    void Deposit(decimal amount);
    void Withdraw(decimal amount);
    decimal GetBalance();
}

// Concrete Product: Savings Account
public class SavingsAccount : IAccount
{
    private decimal _balance;

    public void Deposit(decimal amount)
    {
        _balance += amount;
        Console.WriteLine($"Deposited {amount:C}. Current balance: {_balance:C}");
    }

    public void Withdraw(decimal amount)
    {
        if (_balance >= amount)
        {
            _balance -= amount;
            Console.WriteLine($"Withdrawn {amount:C}. Current balance: {_balance:C}");
        }
        else
        {
            Console.WriteLine("Insufficient funds.");
        }
    }

    public decimal GetBalance()
    {
        return _balance;
    }
}

// Concrete Product: Checking Account
public class CheckingAccount : IAccount
{
    private decimal _balance;

    public void Deposit(decimal amount)
    {
        _balance += amount;
        Console.WriteLine($"Deposited {amount:C}. Current balance: {_balance:C}");
    }

    public void Withdraw(decimal amount)
    {
        if (_balance - amount >= 0)
        {
            _balance -= amount;
            Console.WriteLine($"Withdrawn {amount:C}. Current balance: {_balance:C}");
        }
        else
        {
            Console.WriteLine("Insufficient funds.");
        }
    }

    public decimal GetBalance()
    {
        return _balance;
    }
}

// Creator: AccountFactory interface
public interface IAccountFactory
{
    IAccount CreateAccount();
}

// Concrete Creator: Savings Account Factory
public class SavingsAccountFactory : IAccountFactory
{
    public IAccount CreateAccount()
    {
        return new SavingsAccount();
    }
}

// Concrete Creator: Checking Account Factory
public class CheckingAccountFactory : IAccountFactory
{
    public IAccount CreateAccount()
    {
        return new CheckingAccount();
    }
}

// Client code
public class Program
{
    public static void Main(string[] args)
    {
        // Creating a savings account
        IAccountFactory savingsFactory = new SavingsAccountFactory();
        IAccount savingsAccount = savingsFactory.CreateAccount();

        // Depositing and withdrawing from savings account
        savingsAccount.Deposit(1000);
        savingsAccount.Withdraw(200);

        // Creating a checking account
        IAccountFactory checkingFactory = new CheckingAccountFactory();
        IAccount checkingAccount = checkingFactory.CreateAccount();

        // Depositing and withdrawing from checking account
        checkingAccount.Deposit(500);
        checkingAccount.Withdraw(300);
    }
}
```

4. **Decorator Pattern**:

* **Real-life Example**: Adding functionality to a user interface component in a graphical application. For instance, adding scrollbars to a window.
* **Explanation**: Allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class.

5. **Strategy Pattern**:

* **Real-life Example**: Different algorithms for sorting data (e.g., quicksort, mergesort, bubblesort). The strategy pattern allows the selection of the algorithm at runtime.
* **Explanation**: Defines a family of algorithms, encapsulates each one, and makes them interchangeable. This pattern lets the algorithm vary independently from clients that use it.

```csharp
using System;

// Strategy Interface
public interface IPaymentStrategy
{
    void Pay(decimal amount);
}

// Concrete Strategies
public class CreditCardPayment : IPaymentStrategy
{
    private string cardNumber;

    public CreditCardPayment(string cardNumber)
    {
        this.cardNumber = cardNumber;
    }

    public void Pay(decimal amount)
    {
        Console.WriteLine($"Paying {amount:C} using Credit Card (Number: {cardNumber}).");
    }
}

public class PayPalPayment : IPaymentStrategy
{
    private string email;

    public PayPalPayment(string email)
    {
        this.email = email;
    }

    public void Pay(decimal amount)
    {
        Console.WriteLine($"Paying {amount:C} using PayPal (Email: {email}).");
    }
}

public class CryptoPayment : IPaymentStrategy
{
    private string walletAddress;

    public CryptoPayment(string walletAddress)
    {
        this.walletAddress = walletAddress;
    }

    public void Pay(decimal amount)
    {
        Console.WriteLine($"Paying {amount:C} using Cryptocurrency (Wallet Address: {walletAddress}).");
    }
}

// Context
public class PaymentContext
{
    private IPaymentStrategy paymentStrategy;

    public void SetPaymentStrategy(IPaymentStrategy strategy)
    {
        this.paymentStrategy = strategy;
    }

    public void ProcessPayment(decimal amount)
    {
        if (paymentStrategy == null)
        {
            throw new InvalidOperationException("Payment strategy is not set.");
        }

        paymentStrategy.Pay(amount);
    }
}

// Program
class Program
{
    static void Main()
    {
        PaymentContext paymentContext = new PaymentContext();

        // Pay using Credit Card
        paymentContext.SetPaymentStrategy(new CreditCardPayment("1234-5678-9876-5432"));
        paymentContext.ProcessPayment(120.00m);

        // Pay using PayPal
        paymentContext.SetPaymentStrategy(new PayPalPayment("user@example.com"));
        paymentContext.ProcessPayment(75.50m);

        // Pay using Cryptocurrency
        paymentContext.SetPaymentStrategy(new CryptoPayment("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"));
        paymentContext.ProcessPayment(250.00m);
    }
}

```

6. **Command Pattern**:

* **Real-life Example**: Implementing undo functionality in a text editor. Each action (like typing or deleting) is encapsulated as an object that can be stored and executed.
* **Explanation**: Encapsulates a request as an object, thereby allowing for parameterization of clients with queues, requests, and operations.

7. **Adapter Pattern**:

* **Real-life Example**: Integrating with a third-party library where the interface does not match the rest of your application. An adapter can translate calls from your application to the third-party library. Payment gateway third party
* **Explanation**: 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.

```csharp
using System;

namespace AdapterPattern
{
    // Target Interface
    public interface IPaymentGateway
    {
        void ProcessPayment(string cardNumber, string cardHolderName, DateTime expiryDate, decimal amount);
    }

    // Adaptee: Third-party payment gateway
    public class ThirdPartyPaymentGateway
    {
        public void Pay(string cardNumber, string cardHolder, string expiry, decimal amount)
        {
            Console.WriteLine($"Payment of {amount:C} processed by ThirdPartyPaymentGateway for card {cardNumber}.");
        }
    }

    // Adapter: Adapts ThirdPartyPaymentGateway to IPaymentGateway
    public class PaymentGatewayAdapter : IPaymentGateway
    {
        private readonly ThirdPartyPaymentGateway _thirdPartyPaymentGateway;

        public PaymentGatewayAdapter(ThirdPartyPaymentGateway thirdPartyPaymentGateway)
        {
            _thirdPartyPaymentGateway = thirdPartyPaymentGateway;
        }

        public void ProcessPayment(string cardNumber, string cardHolderName, DateTime expiryDate, decimal amount)
        {
            // Convert expiryDate to string format expected by the third-party gateway
            string expiry = expiryDate.ToString("MM/yy");
            _thirdPartyPaymentGateway.Pay(cardNumber, cardHolderName, expiry, amount);
        }
    }

    // Client code
    class Program
    {
        static void Main(string[] args)
        {
            // Create an instance of the third-party payment gateway
            ThirdPartyPaymentGateway thirdPartyPaymentGateway = new ThirdPartyPaymentGateway();

            // Create an instance of the adapter
            IPaymentGateway paymentGateway = new PaymentGatewayAdapter(thirdPartyPaymentGateway);

            // Use the payment gateway via the adapter
            paymentGateway.ProcessPayment("1234-5678-9012-3456", "John Doe", new DateTime(2025, 12, 31), 100.00m);
            // Output: Payment of $100.00 processed by ThirdPartyPaymentGateway for card 1234-5678-9012-3456.
        }
    }
}
```

8. **Prototype Pattern**:

* **Real-life Example**: Creating objects in a graphic application (e.g., shapes, drawings). Instead of creating new instances from scratch, a prototype pattern clones existing objects.
* **Explanation**: Specifies the kind of objects to create using a prototypical instance, and creates new objects by copying this prototype.

9. **Builder Pattern**:
   * **Real-life Example**: Constructing complex objects such as vehicles, where different parts like engine, wheels, and body can be configured step-by-step.
   * **Explanation**: Separates the construction of a complex object from its representation so that the same construction process can create different representations.
10. **Facade Pattern**:
    * **Real-life Example**: Simplifying interactions with a complex library or framework (e.g., a library for 3D graphics). A facade provides a simplified interface to the complex subsystems. Banking system
    * **Explanation**: Provides a unified interface to a set of interfaces in a subsystem, making the subsystem easier to use.

```csharp
using System;

namespace FacadePattern
{
    // Subsystem Class 1
    public class AccountService
    {
        public void GetAccountDetails(string accountId)
        {
            Console.WriteLine($"Fetching account details for account ID: {accountId}");
        }
    }

    // Subsystem Class 2
    public class TransferService
    {
        public void TransferAmount(string fromAccount, string toAccount, decimal amount)
        {
            Console.WriteLine($"Transferring {amount:C} from {fromAccount} to {toAccount}");
        }
    }

    // Subsystem Class 3
    public class LoanService
    {
        public void ApplyForLoan(string accountId, decimal loanAmount)
        {
            Console.WriteLine($"Applying for a loan of {loanAmount:C} for account ID: {accountId}");
        }
    }

    // Facade Class
    public class BankingFacade
    {
        private readonly AccountService _accountService;
        private readonly TransferService _transferService;
        private readonly LoanService _loanService;

        public BankingFacade()
        {
            _accountService = new AccountService();
            _transferService = new TransferService();
            _loanService = new LoanService();
        }

        public void GetAccountDetails(string accountId)
        {
            _accountService.GetAccountDetails(accountId);
        }

        public void TransferAmount(string fromAccount, string toAccount, decimal amount)
        {
            _transferService.TransferAmount(fromAccount, toAccount, amount);
        }

        public void ApplyForLoan(string accountId, decimal loanAmount)
        {
            _loanService.ApplyForLoan(accountId, loanAmount);
        }
    }

    // Client code
    class Program
    {
        static void Main(string[] args)
        {
            BankingFacade bankingFacade = new BankingFacade();

            // Use the facade to perform various operations
            bankingFacade.GetAccountDetails("12345");
            bankingFacade.TransferAmount("12345", "67890", 500.00m);
            bankingFacade.ApplyForLoan("12345", 10000.00m);
        }
    }
}

```

9. **Proxy Pattern**:
   * **Real-life Example**: Accessing a remote service or resource. A proxy can control access to the original object, allowing additional functionalities like lazy initialization, logging, or access control.
   * **Explanation**: Provides a surrogate or placeholder for another object to control access to it.
10. **Chain of Responsibility Pattern**:
    * **Real-life Example**: Support Ticket Processing System. Imagine a support ticket system where a customer support request could be handled by multiple levels of support staff: Level 1, Level 2, and Level 3 support. Each level of support will try to handle the request, and if it cannot, it will pass the request to the next level.
    * **Explanation**: Passes a request along a chain of handlers. Each handler decides either to process the request or to pass it to the next handler in the chain.

```csharp
using System;

namespace ChainOfResponsibilityExample
{
    // Enum for issue severity
    public enum IssueSeverity
    {
        Low,
        Medium,
        High
    }

    // Support ticket class
    public class SupportTicket
    {
        public IssueSeverity IssueSeverity { get; set; }
        public string Description { get; set; }

        public SupportTicket(IssueSeverity severity, string description)
        {
            IssueSeverity = severity;
            Description = description;
        }
    }

    // Abstract handler
    public abstract class SupportHandler
    {
        protected SupportHandler _nextHandler;

        public void SetNextHandler(SupportHandler nextHandler)
        {
            _nextHandler = nextHandler;
        }

        public abstract void HandleRequest(SupportTicket ticket);
    }

    // Concrete handler for Level 1 support
    public class Level1SupportHandler : SupportHandler
    {
        public override void HandleRequest(SupportTicket ticket)
        {
            if (ticket.IssueSeverity == IssueSeverity.Low)
            {
                Console.WriteLine("Level 1 Support: Handling low severity issue.");
            }
            else if (_nextHandler != null)
            {
                _nextHandler.HandleRequest(ticket);
            }
        }
    }

    // Concrete handler for Level 2 support
    public class Level2SupportHandler : SupportHandler
    {
        public override void HandleRequest(SupportTicket ticket)
        {
            if (ticket.IssueSeverity == IssueSeverity.Medium)
            {
                Console.WriteLine("Level 2 Support: Handling medium severity issue.");
            }
            else if (_nextHandler != null)
            {
                _nextHandler.HandleRequest(ticket);
            }
        }
    }

    // Concrete handler for Level 3 support
    public class Level3SupportHandler : SupportHandler
    {
        public override void HandleRequest(SupportTicket ticket)
        {
            if (ticket.IssueSeverity == IssueSeverity.High)
            {
                Console.WriteLine("Level 3 Support: Handling high severity issue.");
            }
            else
            {
                Console.WriteLine("Issue could not be handled.");
            }
        }
    }

    // Main program
    class Program
    {
        static void Main(string[] args)
        {
            // Create handlers
            var level1 = new Level1SupportHandler();
            var level2 = new Level2SupportHandler();
            var level3 = new Level3SupportHandler();

            // Set up the chain of responsibility
            level1.SetNextHandler(level2);
            level2.SetNextHandler(level3);

            // Create support tickets
            var ticket1 = new SupportTicket(IssueSeverity.Low, "Password reset");
            var ticket2 = new SupportTicket(IssueSeverity.Medium, "Unable to access account");
            var ticket3 = new SupportTicket(IssueSeverity.High, "System outage");

            // Process the tickets
            level1.HandleRequest(ticket1);
            level1.HandleRequest(ticket2);
            level1.HandleRequest(ticket3);
        }
    }
}

```

9. **Composite Pattern**:
   * **Real-life Example**: Representing a hierarchy of graphical objects, where individual objects (e.g., lines, circles) and groups of objects are treated uniformly.
   * **Explanation**: Composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions uniformly.
10. **Flyweight Pattern**:
    * **Real-life Example**: Managing a large number of fine-grained objects efficiently, such as characters in a text editor. Flyweight minimizes memory usage by sharing as much data as possible.
    * **Explanation**: Uses sharing to support large numbers of fine-grained objects efficiently.
11. **State Pattern**:
    * **Real-life Example**: A vending machine that changes its behavior based on the current state (e.g., no coin inserted, coin inserted, dispensing product).
    * **Explanation**: Allows an object to alter its behavior when its internal state changes, making the object appear to change its class.
12. **Memento Pattern**:
    * **Real-life Example**: Implementing undo functionality in applications. A memento captures and stores the current state of an object so it can be restored later.
    * **Explanation**: Captures and externalizes an object's internal state so that it can be restored later without violating encapsulation.
13. **Template Method Pattern**:
    * **Real-life Example**: Defining the skeleton of an algorithm in a method in a base class, leaving the implementation of some steps to subclasses. For example, a base class providing a template for document generation with specific steps for different document formats.
    * **Explanation**: Defines the skeleton of an algorithm in an operation, deferring some steps to subclasses.
14. **Visitor Pattern**:
    * **Real-life Example**: Performing operations on a collection of objects with different types (e.g., a compiler performing type checking, optimization, and code generation on an abstract syntax tree).
    * **Explanation**: Represents an operation to be performed on elements of an object structure, allowing new operations to be defined without changing the classes of the elements on which it operates.
15. **Mediator Pattern**:
    * **Real-life Example**: Managing interactions between multiple components in a user interface. Instead of each component interacting directly with every other component, a mediator handles the communication, reducing dependencies. Chat Room example
    * **Explanation**: Defines an object that encapsulates how a set of objects interact, promoting loose coupling by keeping objects from referring to each other explicitly.

```csharp
using System;
using System.Collections.Generic;

// Mediator Interface
public interface IChatRoomMediator
{
    void SendMessage(string message, User user);
    void RegisterUser(User user);
}

// Concrete Mediator
public class ChatRoom : IChatRoomMediator
{
    private readonly Dictionary<string, User> _users = new Dictionary<string, User>();

    public void RegisterUser(User user)
    {
        if (!_users.ContainsKey(user.Name))
        {
            _users[user.Name] = user;
        }

        user.SetChatRoom(this);
    }

    public void SendMessage(string message, User user)
    {
        foreach (var u in _users.Values)
        {
            // Don't send the message to the sender
            if (u != user)
            {
                u.Receive(message, user.Name);
            }
        }
    }
}

// Colleague Interface
public abstract class User
{
    protected IChatRoomMediator _chatRoom;
    public string Name { get; private set; }

    public User(string name)
    {
        Name = name;
    }

    public void SetChatRoom(IChatRoomMediator chatRoom)
    {
        _chatRoom = chatRoom;
    }

    public void Send(string message)
    {
        Console.WriteLine($"{Name} sends: {message}");
        _chatRoom.SendMessage(message, this);
    }

    public abstract void Receive(string message, string from);
}

// Concrete Colleague
public class ChatUser : User
{
    public ChatUser(string name) : base(name) { }

    public override void Receive(string message, string from)
    {
        Console.WriteLine($"{Name} received from {from}: {message}");
    }
}

// Client Code
public class Program
{
    public static void Main(string[] args)
    {
        IChatRoomMediator chatRoom = new ChatRoom();

        User user1 = new ChatUser("Alice");
        User user2 = new ChatUser("Bob");
        User user3 = new ChatUser("Charlie");

        chatRoom.RegisterUser(user1);
        chatRoom.RegisterUser(user2);
        chatRoom.RegisterUser(user3);

        user1.Send("Hello, everyone!");
        user2.Send("Hi Alice!");
        user3.Send("Hey Alice and Bob!");
    }
}
```
