Created: 3/20/2017
Updated: 8/14/2017
Creational patterns deal with instantiating objects.
What: An object that creates other objects.
Why: 1) Having a single object handle multiple variations based on its parameters can increase complexity for maintenance.
2) Furthermore, determining which object instance to create may have external dependencies. Use factory methods to create objects
without having to specify the exact class instance to decouple the class from external dependencies. A factory method returns either
an interface or a child class (of the factory class).
Example:
class Factory
{
IProduct createProduct(enum externalDependency)
{
switch (externalDependency)
{
case ProductOneType:
return new ProductOne();
case ProductTwoType:
return new ProductTwo();
default:
throw new Exception($"Invalid enum: {externalDependency}");
}
}
}
Interface IProduct { ... }
class ProductOne : IProduct { ... }
class ProductTwo : IProduct { ... }
What: An object that receives parameters step-by-step and returns a constructed object from the provided parameters.
Why: Having too many parameters can make a method difficult to maintain and use. The builder pattern can be used to
pass parameters to create an object over a series of steps. The builder pattern also can be used to avoid the need to have
multiple constructors, which may also be problematic for maintenance.
Example:
class FaceBuilder
{
public FaceBuilder();
void SetEars(Ears ears);
void SetEyes(Eyes eyes);
void SetMouth(Mouth mouth);
void SetNose(Nose nose);
Face GetFace(); // returns the Face object consisting of the facial features set through the set methods
}
FaceBuilder builder = new FaceBuilder();
builder.SetEars(Ears);
builder.SetEyes(Eyes);
builder.SetMouth(Mouth);
builder.SetNose(Nose);
Face face = builder.GetFace();
What: Use clone method to produce new objects.
Why: The pattern is used to 1) avoid specifying the concrete subclasses of an abstract class object (abstraction principle) and to
2) avoid the cost of using the "new" keyword to create new objects when it is prohibitively expensive.
Example:
abstract class AbstractObject
{
public abstract AbstractObject ShallowClone();
}
class ConcreteObject : AbstractObject
{
public override AbstractObject ShallowClone()
{
return (AbstractObject)this.MemberwiseClone(); // shallow copy
}
}
What: A pattern that restricts a program from creating more than one instantiation of a class object.
Generally, it is implemented using a single static instance.
Why: The singleton pattern is useful when there is exactly one instance that is needed as it saves on resource allocation.
There is an advantage to using the singleton pattern over a static class when abstraction or inheritance is involved.
Example:
// Using lazy initialization
public class Singleton
{
private static Singleton s_instance = null;
private static object s_lock = new object();
public static Singleton Instance
{
get
{
if (s_instance == null)
{
lock(s_lock)
{
if (s_instance == null)
s_instance = new Instance();
}
}
return s_instance;
}
}
}
Structural patterns deal with the composition of entities.
What: Wraps an existing class and exposes an interface with modifications to the functionality.
The adapter encapsulates the interface of the adaptee.
Why: Allows an existing class implementation to be used from another interface. The adapter pattern
is often used to get existing classes to work with other classes without having to change their source code.
Generally, the adaptee is a data member of the implemented adapter.
Example:
class Adapter
{
private Adaptee adaptee;
public Adapter(Adaptee a)
{
adaptee = a;
}
public string AdaptedStringMethod()
{
return Format(adaptee.StringMethod());
}
}
What: A bridge is created when an abstraction takes in an interface to handle certain implementations.
Why: Intended to "decouple an abstraction from its implementation so that the two can vary independently." (Design Patterns)
Example:
interface IComponent
{
void function();
}
class ConcreteComponent : IComponent
{
public void function() { }
}
interface IAbstraction
{
void ExecuteFunction();
}
class Concretion : IAbstraction
{
public IComponent component;
public Concretion(IComponent component)
{
this.component = component;
}
public void ExecuteFunction()
{
this.component.function();
}
}
What: Composing an object out of a group of objects in a tree-like structure, such that the individual objects and the
composition can be treated uniformly.
Why: To simplify working with tree-like structured data where a leaf node and branch may be treated differently.
Example:
interface IComposite
{
void Print();
}
public class Concretebase : IComposite
{
public void Print() { ... }
}
public class Composite : IComposite
{
public void Append(IComposite comp) { }
public void Print() { ... }
}
What: Add behaviors to individual objects without modifying the behavior of the objects internally.
Why: The purpose of a decorator class is to have a single responsibility, such that it provides one
decoration to reduce complexity.
Example:
interface IComponent
{
void Print();
}
public class Component : IComponent
{
public void Print() { ... }
}
public abstract ComponentDecorator : IComponent
{
private IComponent component;
public ComponentDecorator(IComponent component)
{
this.component = component;
}
public void Print()
{
this.component.Print();
}
}
public class AddSomething : ComponentDecorator
{
public AddSomething(IComponent component) : base(component)
{
}
public void Print()
{
base.Print();
Console.Writeline("AddSomething");
}
}
What: A class that provides a simplified interface to a larger body of code, such as a class library.
Why: To simplify an existing library.
Example:
public class Facade
{
private WrappedClassA classA = new WrappedClassA();
private WrappedClassB classB = new WrappedClassB();
public void Method1()
{
// Do something with classA and/or classB
}
public void Method2()
{
// Do something with classA and/or classB
}
}
What: A class that makes use of sharing data as much as possible.
Why: Minimizes memory usage by sharing data with similar objects. A common practice is to
"hold shared data in external data structures and pass them to the flyweight objects temporarily when they are used." (Wikipedia)
Example:
interface IComponent
{
object GetData();
}
public class FlyweightObject : IComponent
{
private static readonly object s_lock = new object();
private static object s_cache = null;
public object GetData()
{
if (s_cache != null)
return s_cache;
return LoadData();
}
private void LoadData()
{
if (s_cache == null)
{
lock (s_lock)
{
if (s_cache == null)
s_cache = LoadDataFromDatabase();
}
}
}
}
What: A class functioning as a gateway to another class. A proxy is implemented using the same
interface as the class it is serving as a proxy for.
Why: To internally handle validation, optimizations, hide information, and do additional house-keeping job.
Example:
interface IComponent
{
object GetData();
}
public class Component : IComponent
{
private object m_data;
public Component(object a_data) { this. m_data = a_data; }
public object GetData()
{
return this.m_data;
}
}
public class ProxyComponent : IComponent
{
private Component m_component;
public ProxyComponent(object a_data)
{
this. m_component = new Component(a_data);
}
public object GetData()
{
object data = this.m_component.GetData();
if (data == null)
throw new Exception("data is not initialized");
return data;
}
}
Behavioral patterns deal with communication between objects.
What: A pattern where processing objects handle tasks they can handle and pass other tasks onto the next processing object.
Why: To loosely couple the objects in a chain. This allows the processing to be chained or arranged in any order.
Example:
public abstract class AbstractProcessor
{
private AbstractProcessor m_nextProcessor;
public AbstractProcessor ()
{
}
public string SetNext(AbstractProcessor a_nextProcessor)
{
this. m_nextProcessor = a_nextProcessor;
}
public abstract void Process()
{
if (this.m_nextProcessor != null)
this.m_nextProcessor.Process();
}
}
public class ProcessorA : AbstractProcessor
{
public ProcessorA()
{
}
public override void Process()
{
// if (QualifyToProcess)
// Process...
// else
base.Process();
}
}
ProcessorA a = new ProcessorA();
ProcessorB b = new ProcessorB();
ProcessorC c = new ProcessorC();
a.SetNext(b);
b.SetNext(c);
What: A pattern where the client decides the invoker, command, and receiver. The invoker calls the appropriate
command when invoked by the client. The command in turn calls the receiver. The receiver then executes.
Why: To loosely couple the invoker, commands, and receivers. This allows the commands and receivers to be easily
interchanged and reused.
Client - The caller that determines the receiver, command, and invoker (e.g. web service API).
Invoker - The entity invoking the command (e.g. user, actor, button, keyboard key).
Command - The action/event (e.g. submit request).
Receiver - The entity action is applied to (e.g. actor, request).
Example:
public interface IReceiver
{
// actions
void ExecuteA();
void ExecuteB();
}
public class Receiver : IReceiver
{
public void ExecuteA() { }
public void ExecuteB() { }
}
public interface ICommand
{
void Execute();
}
public class CommandA : ICommand
{
private IReceiver m_receiver;
public CommandA(IReceiver a_receiver)
{
this. m_receiver = a_receiver;
}
public void Execute()
{
this.m_receiver.ExecuteA();
}
}
public class CommandB : ICommand
{
private IReceiver m_receiver;
public CommandB(IReceiver a_receiver)
{
this. m_receiver = a_receiver;
}
public void Execute()
{
this.m_receiver.ExecuteB();
}
}
public class Invoker
{
private ICommand m_commandA;
private ICommand m_commandB;
public Invoker(ICommand a_commandA, ICommand a_commandB)
{
this.m_commandA = a_commandA;
this.m_commandB = a_commandB;
}
public void InvokeA()
{
this.m_commandA.Execute();
}
public void InvokeB()
{
this.m_commandB.Execute();
}
}
public class Client
{
public Client() { }
public void ExecuteClient()
{
IReceiver receiver = new Receiver();
ICommand commandA = new CommandA(receiver);
ICommand commandB = new CommandB(receiver);
Invoker invoker = new Invoker(commandA, commandB);
// if match certain condition for A
invoker.InvokeA();
// if match certain condition for B
invoker.InvokeB();
}
}
What: A pattern that uses tokenized data to interpret languages.
Why: To make use of the composite pattern when interpreting a language.
Example:
public interface IExpression
{
public object Interpret(Dictionary
What: A pattern that exposes an interface to access objects in collections sequentially without
exposing the underlying implementations of the collections.
Why: To decouple the algorithms from specific collections.
Example:
public interface IEnumerator
{
object Current { get; }
bool MoveNext();
void Reset();
}
public class SampleCollection : IEnumerator
{
private object[] m_arrData;
private int m_nCurrIndex;
public SampleCollection(object[] a_arrData)
{
this.m_arrData = a_arrData;
this.m_nCurrIndex = 0;
}
public object Current
{
get {
return this.m_arrData != null && this. m_nCurrIndex < this.m_arrData.Length ? this.m_arrData[this. m_nCurrIndex] ? null;
}
}
public bool MoveNext() { ++this.m_nCurrIndex; }
public void Reset() { this.m_nCurrIndex = 0; }
}
What: A pattern making use of a class object that encapsulates interactions between multiple other classes.
Why: A program often contains multiple classes that interact with each other, which may increase the complexity
of the code. The pattern can be used to reduce complexity and loosely couple multiple classes with the callers.
Example:
// Defines interface for colleague interaction
public interface IColleague
{
void Action();
}
// Defines interface for mediation
public interface IMediator
{
void Execute(State a_state);
}
public class Mediator : IMediator
{
private IColleague[] m_actors;
public Mediator(IColleague[] a_actors)
{
this.m_actors = a_actors;
}
// Decouple State and IColleague
public void Execute(State a_state)
{
IEnumerable[] sortedActors = this.m_actors.Sort( (a1, a2)=> a_state[a1].Priority.CompareTo(a_state[a2].Priority));
foreach (IColleague actor in this.m_actors)
{
Status eStatus = a_state[actor].Status;
if (eStatus == Status.Active)
actor.Action();
}
}
}
What: A pattern where a previous state is stored to enable undoing a change.
Why: Enables the ability to capture the internal state of an object without violating encapsulation.
Caretaker - The entity that applies and undo changes to the originator.
Originator - The entity change is applied to.
Memento - A preserved state of the originator.
Example:
public class Memento
{
public readonly string State;
public Memento(string a_sState)
{
this.State = a_sState;
}
}
public class Originator
{
public int Data;
public Originator()
{
}
private string Serialize()
{
return this.Data.ToString();
}
private static Originator Deserialize(string a_sSerializedData)
{
Originator originator = new Originator();
originator.Data = Convert.ToInt(a_sSerializedData);
return originator;
}
public Memento GetCurrentState()
{
return new Memento(this.Serialize());
}
public void RestoreState(Memento a_memento)
{
Originator old = Originator.Deserialize(a_memento.State);
this.Data = old.Data;
}
}
public class Caretaker
{
public static void main(String[] args)
{
Originator originator = new Originator();
originator.Data = 1;
Memento savedData = originator.GetCurrentState();
originator.Data = 2;
originator.RestoreState(savedData);
}
}
What: A pattern where an object, known as the subject, maintains a list of objects, known as observers,
to notify by invoking their methods when a state change occurs.
Why: Enables event-driven architecture.
Caution: The observer pattern has the subject registering and deregistering observers, which may lead to
memory leaks if the observers are not deregistered accordingly. This issue is non-existent with the message queue
system where the observers can be decoupled from the subject.
Example:
public class Observer
{
public void Notify(Info a_info)
{
// handle notification
}
}
public class ObservableSubject
{
private List
What: A pattern that models states as class objects implementing the state pattern interface. It is an object-oriented
representation of a state machine.
Why: Encapsulates the behavior of an object based on its state and avoid monolithic conditional statements stemming
from handling the different states.
Example:
public interface IState
{
void Execute(StateContext a_state);
}
public class StateA : IState
{
public StateA()
{
}
public void Execute(StateContext a_state)
{
if (a_state.HasData)
// Execute on a_state data
a_state.SetState(nextState);
}
}
public class StateContext
{
private IState m_state;
public StateContext()
{
this.m_state = new StateA();
}
public void Execute()
{
this.m_state.Execute(this);
}
public void SetState(IState a_state)
{
this.m_state = a_state;
}
}
What: A pattern where the behavior of the class object is determined at runtime.
Why: Decouples the behavior from the class object.
Example:
public interface IStrategy
{
public void Execute(string a_data);
}
public class StrategyA : IStrategy
{
public StrategyA()
{
}
public void Execute(string a_data)
{
// Do something with the data
}
}
public class Client
{
private IStrategy m_strategy;
public Client(IStrategy a_strategy)
{
this.m_strategy = a_strategy;
}
public void Execute(string a_data)
{
this.m_strategy.Execute(a_data);
}
public void SetStrategy(IStrategy a_strategy)
{
this.m_strategy = a_strategy;
}
}
What: A pattern where the skeleton of an algorithm is defined, and a subset of steps within
the algorithm can be overridden or are implemented by subclasses.
Why: Allows the general structure of an algorithm to be centralized and reused.
Example:
public interface IOperation
{
void DoStep1();
void DoStep2();
void DoStep3();
}
public class Operation : IOperation
{
public void DoStep1()
{
Console.Write("Sleep");
}
public void DoStep2()
{
Console.Write("Dance");
}
public void DoStep3()
{
Console.Write("Shower");
}
}
public class SomeClass
{
public void TemplateMethod(MoodEnum a_eMood, IOperation a_operation)
{
while (a_eMood == MoodEnum.Tired)
{
a_operation.DoStep1();
}
if (a_eMood == MoodEnum.Happy)
a_operation.DoStep2();
a_operation.DoStep3();
}
}
What: A pattern where an algorithm is separated from the class and centralized inside of another class.
Why: Allows the ability to extend functionality to a class without modifying the class. This is one
way to satisfy the open/closed principle.
Example:
public interface IVisitor
{
void Visit(InstanceA a_data);
void Visit(InstanceB a_data);
}
public interface IInstance
{
void Accept(IVisitor a_visitor);
}
// Functionality extension
public class BillingVisitor : IVisitor
{
public void Visit(InstanceA a_data)
{
Bill(a_data);
}
public void Visit(InstanceB a_data)
{
Bill(a_data);
}
}
public class InstanceA : IInstance
{
public void Accept(IVisitor a_visitor)
{
a_visitor.Visit(this);
}
}
public class InstanceB : IInstance
{
public void Accept(IVisitor a_visitor)
{
a_visitor.Visit(this);
}
}
public class Program
{
public static void main(String[] args)
{
InstanceA instanceA = new InstanceA();
instanceA.Accept(new BillingVisitor());
}
}