Behavioral Patterns
Behavioral patterns tập trung vào việc giao tiếp giữa objects và cách assign responsibilities cho objects, giúp code dễ maintain và mở rộng hơn.
1. Observer Pattern
Mục đích: Định nghĩa one-to-many dependency giữa objects, khi một object thay đổi, tất cả dependents được notify.
C# Implementation
public interface IObserver
{
void Update(string message);
}
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
public class Subject : ISubject
{
private readonly List<IObserver> _observers = new();
private string _state;
public string State
{
get => _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
{
private readonly string _name;
public ConcreteObserver(string name) => _name = name;
public void Update(string message)
{
Console.WriteLine($"{_name} received: {message}");
}
}
Use Cases
- Event systems
- UI data binding
- Real-time updates
- Logging và monitoring
2. Strategy Pattern
Mục đích: Định nghĩa family of algorithms, encapsulate mỗi algorithm, và làm chúng interchangeable.
C# Implementation
public interface ISortStrategy<T>
{
void Sort(List<T> items);
}
public class BubbleSortStrategy<T> : ISortStrategy<T> where T : IComparable<T>
{
public void Sort(List<T> items)
{
// Bubble sort implementation
Console.WriteLine("Sorting using Bubble Sort");
}
}
public class QuickSortStrategy<T> : ISortStrategy<T> where T : IComparable<T>
{
public void Sort(List<T> items)
{
// Quick sort implementation
Console.WriteLine("Sorting using Quick Sort");
}
}
public class Sorter<T>
{
private ISortStrategy<T> _strategy;
public Sorter(ISortStrategy<T> strategy) => _strategy = strategy;
public void SetStrategy(ISortStrategy<T> strategy) => _strategy = strategy;
public void Sort(List<T> items) => _strategy.Sort(items);
}
Use Cases
- Payment processing (different payment methods)
- Compression algorithms
- Authentication strategies
- Sorting và searching algorithms
3. Command Pattern
Mục đích: Encapsulate request as an object, cho phép parameterize và queue requests.
C# Implementation
public interface ICommand
{
void Execute();
void Undo();
}
public class Light
{
public void On() => Console.WriteLine("Light is ON");
public void Off() => Console.WriteLine("Light is OFF");
}
public class LightOnCommand : ICommand
{
private readonly Light _light;
public LightOnCommand(Light light) => _light = light;
public void Execute() => _light.On();
public void Undo() => _light.Off();
}
public class RemoteControl
{
private ICommand _command;
public void SetCommand(ICommand command) => _command = command;
public void PressButton() => _command.Execute();
public void PressUndo() => _command.Undo();
}
Use Cases
- Undo/Redo functionality
- Transaction management
- Task scheduling
- Macro recording
4. State Pattern
Mục đích: Cho phép object thay đổi behavior khi internal state thay đổi.
C# Implementation
public interface IState
{
void InsertCoin(VendingMachine machine);
void SelectProduct(VendingMachine machine);
public string GetStateName();
}
public class VendingMachine
{
public IState CurrentState { get; set; }
public int CoinCount { get; private set; }
public VendingMachine()
{
CurrentState = new NoCoinState();
}
public void InsertCoin()
{
CurrentState.InsertCoin(this);
}
public void SelectProduct()
{
CurrentState.SelectProduct(this);
}
}
public class NoCoinState : IState
{
public void InsertCoin(VendingMachine machine)
{
machine.CoinCount++;
machine.CurrentState = new HasCoinState();
Console.WriteLine("Coin inserted");
}
public void SelectProduct(VendingMachine machine)
{
Console.WriteLine("Please insert coin first");
}
}
public class HasCoinState : IState
{
public void InsertCoin(VendingMachine machine)
{
Console.WriteLine("Coin already inserted");
}
public void SelectProduct(VendingMachine machine)
{
Console.WriteLine("Product dispensed");
machine.CurrentState = new NoCoinState();
}
}
Use Cases
- Order processing workflows
- Game state management
- Document approval workflows
- TCP connection states
5. Template Method Pattern
Mục đích: Định nghĩa skeleton của algorithm, để subclasses override specific steps.
C# Implementation
public abstract class DataMiner
{
// Template method
public void Mine(string path)
{
var file = OpenFile(path);
var data = ExtractData(file);
var parsed = ParseData(data);
var analysis = AnalyzeData(parsed);
SendReport(analysis);
CloseFile(file);
}
protected abstract object ExtractData(object file);
protected abstract object ParseData(object data);
protected abstract string AnalyzeData(object parsed);
protected virtual object OpenFile(string path)
{
Console.WriteLine($"Opening file: {path}");
return new object();
}
protected virtual void CloseFile(object file)
{
Console.WriteLine("Closing file");
}
protected virtual void SendReport(string analysis)
{
Console.WriteLine($"Report: {analysis}");
}
}
public class PDFDataMiner : DataMiner
{
protected override object ExtractData(object file)
{
Console.WriteLine("Extracting PDF data");
return new object();
}
protected override object ParseData(object data)
{
Console.WriteLine("Parsing PDF data");
return new object();
}
protected override string AnalyzeData(object parsed)
{
return "PDF Analysis Result";
}
}
Use Cases
- Data processing pipelines
- Build processes
- Test frameworks
- Data import/export
6. Chain of Responsibility Pattern
Mục đích: Pass request along a chain of handlers, mỗi handler decide xử lý request hoặc pass tiếp.
C# Implementation
public abstract class Handler
{
private Handler _nextHandler;
public Handler SetNext(Handler handler)
{
_nextHandler = handler;
return handler;
}
public void HandleRequest(Request request)
{
if (CanHandle(request))
{
Process(request);
}
else if (_nextHandler != null)
{
_nextHandler.HandleRequest(request);
}
}
protected abstract bool CanHandle(Request request);
protected abstract void Process(Request request);
}
public class AuthHandler : Handler
{
protected override bool CanHandle(Request request)
=> request.RequiresAuth;
protected override void Process(Request request)
{
Console.WriteLine("Authentication successful");
}
}
public class ValidationHandler : Handler
{
protected override bool CanHandle(Request request)
=> request.RequiresValidation;
protected override void Process(Request request)
{
Console.WriteLine("Validation successful");
}
}
Use Cases
- Authentication/Authorization pipelines
- Middleware in web frameworks
- Event handling systems
- Logging levels
7. Iterator Pattern
Mục đích: Truy cập elements của một collection sequentially mà không expose underlying representation.
C# Implementation
public interface IIterator<T>
{
bool HasNext();
T Next();
void Reset();
}
public interface IEnumerable<T>
{
IIterator<T> GetEnumerator();
}
public class BookCollection : IEnumerable<string>
{
private readonly List<string> _books = new();
public void AddBook(string book) => _books.Add(book);
public IIterator<string> GetEnumerator()
{
return new BookIterator(_books);
}
}
public class BookIterator : IIterator<string>
{
private readonly List<string> _books;
private int _position;
public BookIterator(List<string> books)
{
_books = books;
}
public bool HasNext() => _position < _books.Count;
public string Next() => _books[_position++];
public void Reset() => _position = 0;
}
Use Cases
- Collections traversal
- Database result sets
- File processing
- Tree/graph traversal
8. Mediator Pattern
Mục đích: Định nghĩa object encapsulates how a set of objects interact.
C# Implementation
public interface IChatMediator
{
void SendMessage(string message, User sender);
void AddUser(User user);
}
public class ChatRoom : IChatMediator
{
private readonly List<User> _users = new();
public void AddUser(User user) => _users.Add(user);
public void SendMessage(string message, User sender)
{
foreach (var user in _users)
{
if (user != sender)
{
user.Receive(message, sender.Name);
}
}
}
}
public class User
{
public string Name { get; }
private readonly IChatMediator _mediator;
public User(string name, IChatMediator mediator)
{
Name = name;
_mediator = mediator;
}
public void Send(string message) => _mediator.SendMessage(message, this);
public void Receive(string message, string from)
{
Console.WriteLine($"{from}: {message}");
}
}
Use Cases
- Chat applications
- UI event handling
- Air traffic control
- Event aggregation
9. Memento Pattern
Mục đích: Capture và externalize object’s internal state để restore later.
C# Implementation
public class EditorMemento
{
public string Content { get; }
public int CursorPosition { get; }
public DateTime Timestamp { get; }
public EditorMemento(string content, int cursorPosition)
{
Content = content;
CursorPosition = cursorPosition;
Timestamp = DateTime.Now;
}
}
public class Editor
{
public string Content { get; private set; }
public int CursorPosition { get; private set; }
private readonly Stack<EditorMemento> _history = new();
public void Type(string text)
{
Content = Content.Insert(CursorPosition, text);
CursorPosition += text.Length;
}
public EditorMemento Save()
{
return new EditorMemento(Content, CursorPosition);
}
public void Restore(EditorMemento memento)
{
Content = memento.Content;
CursorPosition = memento.CursorPosition;
}
}
Use Cases
- Undo/Redo functionality
- Transaction rollback
- Checkpoints in games
- State snapshots
10. Visitor Pattern
Mục đích: Định nghĩa operation trên elements của một object structure without changing classes.
C# Implementation
public interface IElement
{
void Accept(IVisitor visitor);
}
public class Book : IElement
{
public string Title { get; }
public decimal Price { get; }
public Book(string title, decimal price)
{
Title = title;
Price = price;
}
public void Accept(IVisitor visitor) => visitor.VisitBook(this);
}
public interface IVisitor
{
void VisitBook(Book book);
void VisitMagazine(Magazine magazine);
}
public class PriceCalculator : IVisitor
{
public decimal Total { get; private set; }
public void VisitBook(Book book)
{
Total += book.Price;
Console.WriteLine($"Book: {book.Title} - ${book.Price}");
}
public void VisitMagazine(Magazine magazine)
{
Total += magazine.Price;
Console.WriteLine($"Magazine: {magazine.Title} - ${magazine.Price}");
}
}
Use Cases
- Report generation
- File system operations
- Tax calculation
- Expression tree evaluation
Comparison
| Pattern | Purpose | Complexity |
|---|---|---|
| Observer | Event notifications | Low |
| Strategy | Interchangeable algorithms | Low |
| Command | Encapsulated requests | Medium |
| State | Object state behavior | Medium |
| Template Method | Algorithm skeleton | Low |
| Chain of Responsibility | Sequential handlers | Medium |
| Iterator | Collection traversal | Low |
| Mediator | Object communication | Medium |
| Memento | State restoration | Low |
| Visitor | Operations on structures | Medium |
Best Practices
- Observer: Use for loose coupling, event-driven systems
- Strategy: Use when you need multiple algorithms
- Command: Use for undo, queuing, transactions
- State: Use for state machines
- Template Method: Use for algorithm frameworks
- Chain: Use for processing pipelines
- Iterator: Use for custom traversal
- Mediator: Use for reducing dependencies
- Memento: Use for state snapshots
- Visitor: Use for operations on complex structures