Design patterns are recurring solutions to software design problems you find again and again in real-world application development. Patterns are about design and interaction of objects, as well as providing a communication platform concerning elegant, reusable solutions to commonly encountered programming challenges.
See also here for a detailed explanation of patterns
Creational
Factory pattern
Abstract factory pattern
Builder pattern
Prototype pattern
Singleton
Structural
Decorator pattern
Composite pattern
Facade pattern
Behavioral
Strategy pattern
Chain of responsibility
Visitor pattern
Factory pattern
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
using System; namespace DoFactory.GangOfFour.Abstract.Structural { // MainApp test application class MainApp { public static void Main() { // Abstract factory #1 AbstractFactory factory1 = new ConcreteFactory1(); Client c1 = new Client(factory1); c1.Run(); // Abstract factory #2 AbstractFactory factory2 = new ConcreteFactory2(); Client c2 = new Client(factory2); c2.Run(); // Wait for user input Console.Read(); } } // "AbstractFactory" abstract class AbstractFactory { public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } // "ConcreteFactory1" class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } // "ConcreteFactory2" class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } // "AbstractProductA" abstract class AbstractProductA { } // "AbstractProductB" abstract class AbstractProductB { public abstract void Interact(AbstractProductA a); } // "ProductA1" class ProductA1 : AbstractProductA { } // "ProductB1" class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } // "ProductA2" class ProductA2 : AbstractProductA { } // "ProductB2" class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } // "Client" - the interaction environment of the products class Client { private AbstractProductA AbstractProductA; private AbstractProductB AbstractProductB; // Constructor public Client(AbstractFactory factory) { AbstractProductB = factory.CreateProductB(); AbstractProductA = factory.CreateProductA(); } public void Run() { AbstractProductB.Interact(AbstractProductA); } } }
Abstract Factory pattern
Separate the construction of a complex object from its representation so that the same construction process can create different representations.
using System; using System.Collections; namespace DoFactory.GangOfFour.Builder.Structural { // MainApp test application public class MainApp { public static void Main() { // Create director and builders Director director = new Director(); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2(); // Construct two products director.Construct(b1); Product p1 = b1.GetResult(); p1.Show(); director.Construct(b2); Product p2 = b2.GetResult(); p2.Show(); // Wait for user Console.Read(); } } // "Director" class Director { // Builder uses a complex series of steps public void Construct(Builder builder) { builder.BuildPartA(); builder.BuildPartB(); } } // "Builder" abstract class Builder { public abstract void BuildPartA(); public abstract void BuildPartB(); public abstract Product GetResult(); } // "ConcreteBuilder1" class ConcreteBuilder1 : Builder { private Product product = new Product(); public override void BuildPartA() { product.Add("PartA"); } public override void BuildPartB() { product.Add("PartB"); } public override Product GetResult() { return product; } } // "ConcreteBuilder2" class ConcreteBuilder2 : Builder { private Product product = new Product(); public override void BuildPartA() { product.Add("PartX"); } public override void BuildPartB() { product.Add("PartY"); } public override Product GetResult() { return product; } } // "Product" class Product { ArrayList parts = new ArrayList(); public void Add(string part) { parts.Add(part); } public void Show() { Console.WriteLine("nProduct Parts -------"); foreach (string part in parts) Console.WriteLine(part); } } }
Prototype pattern
Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype.
// Prototype pattern -- Structural example using System; namespace DoFactory.GangOfFour.Prototype.Structural { // MainApp startup class for Structural // Prototype Design Pattern. class MainApp { // Entry point into console application. static void Main() { // Create two instances and clone each ConcretePrototype1 p1 = new ConcretePrototype1("I"); ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone(); Console.WriteLine("Cloned: {0}", c1.Id); ConcretePrototype2 p2 = new ConcretePrototype2("II"); ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone(); Console.WriteLine("Cloned: {0}", c2.Id); // Wait for user Console.ReadKey(); } } // The 'Prototype' abstract class abstract class Prototype { private string _id; // Constructor public Prototype(string id) { this._id = id; } // Gets id public string Id { get { return _id; } } public abstract Prototype Clone(); } // A 'ConcretePrototype' class class ConcretePrototype1 : Prototype { // Constructor public ConcretePrototype1(string id) : base(id) { } // Returns a shallow copy public override Prototype Clone() { return (Prototype)this.MemberwiseClone(); } } // A 'ConcretePrototype' class class ConcretePrototype2 : Prototype { // Constructor public ConcretePrototype2(string id) : base(id) { } // Returns a shallow copy public override Prototype Clone() { return (Prototype)this.MemberwiseClone(); } } }
Singleton pattern
Ensure a class has only one instance and provide a global point of access to it.
// Singleton pattern -- Structural example using System; namespace DoFactory.GangOfFour.Singleton.Structural { // // MainApp startup class for Structural // Singleton Design Pattern. // class MainApp { // // Entry point into console application. // static void Main() { // Constructor is protected -- cannot use new Singleton s1 = Singleton.Instance(); Singleton s2 = Singleton.Instance(); // Test for same instance if (s1 == s2) { Console.WriteLine("Objects are the same instance"); } // Wait for user Console.ReadKey(); } } // // The 'Singleton' class // class Singleton { private static Singleton _instance; // Constructor is 'protected' protected Singleton() { } public static Singleton Instance() { // Uses lazy initialization. // Note: this is not thread safe. if (_instance == null) { _instance = new Singleton(); } return _instance; } } }
Decorator pattern
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
using System; namespace DoFactory.GangOfFour.Decorator.Structural { // MainApp test application class MainApp { static void Main() { // Create ConcreteComponent and two Decorators ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); // Link decorators d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); // Wait for user Console.Read(); } } // "Component" abstract class Component { public abstract void Operation(); } // "ConcreteComponent" class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("ConcreteComponent.Operation()"); } } // "Decorator" abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } // "ConcreteDecoratorA" class ConcreteDecoratorA : Decorator { private string addedState; public override void Operation() { base.Operation(); addedState = "New State"; Console.WriteLine("ConcreteDecoratorA.Operation()"); } } // "ConcreteDecoratorB" class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddedBehavior(); Console.WriteLine("ConcreteDecoratorB.Operation()"); } void AddedBehavior() { } } }
Composite pattern
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
using System; using System.Collections; namespace DoFactory.GangOfFour.Composite.Structural { // MainApp test application class MainApp { static void Main() { // Create a tree structure Composite root = new Composite("root"); root.Add(new Leaf("Leaf A")); root.Add(new Leaf("Leaf B")); Composite comp = new Composite("Composite X"); comp.Add(new Leaf("Leaf XA")); comp.Add(new Leaf("Leaf XB")); root.Add(comp); root.Add(new Leaf("Leaf C")); // Add and remove a leaf Leaf leaf = new Leaf("Leaf D"); root.Add(leaf); root.Remove(leaf); // Recursively display tree root.Display(1); // Wait for user Console.Read(); } } // "Component" abstract class Component { protected string name; // Constructor public Component(string name) { this.name = name; } public abstract void Add(Component c); public abstract void Remove(Component c); public abstract void Display(int depth); } // "Composite" class Composite : Component { private ArrayList children = new ArrayList(); // Constructor public Composite(string name) : base(name) { } public override void Add(Component component) { children.Add(component); } public override void Remove(Component component) { children.Remove(component); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); // Recursively display child nodes foreach (Component component in children) { component.Display(depth + 2); } } } // "Leaf" class Leaf : Component { // Constructor public Leaf(string name) : base(name) { } public override void Add(Component c) { Console.WriteLine("Cannot add to a leaf"); } public override void Remove(Component c) { Console.WriteLine("Cannot remove from a leaf"); } public override void Display(int depth) { Console.WriteLine(new String('-', depth) + name); } } }
Facade pattern
Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.
using System; namespace DoFactory.GangOfFour.Factory.Structural { /// /// MainApp startup class for Structural /// Factory Method Design Pattern. /// class MainApp { /// /// Entry point into console application. /// static void Main() { // An array of creators Creator[] creators = new Creator[2]; creators[0] = new ConcreteCreatorA(); creators[1] = new ConcreteCreatorB(); // Iterate over creators and create products foreach (Creator creator in creators) { Product product = creator.FactoryMethod(); Console.WriteLine("Created {0}", product.GetType().Name); } // Wait for user Console.ReadKey(); } } /// /// The 'Product' abstract class /// abstract class Product { } /// /// A 'ConcreteProduct' class /// class ConcreteProductA : Product { } /// /// A 'ConcreteProduct' class /// class ConcreteProductB : Product { } /// /// The 'Creator' abstract class /// abstract class Creator { public abstract Product FactoryMethod(); } /// /// A 'ConcreteCreator' class /// class ConcreteCreatorA : Creator { public override Product FactoryMethod() { return new ConcreteProductA(); } } /// /// A 'ConcreteCreator' class /// class ConcreteCreatorB : Creator { public override Product FactoryMethod() { return new ConcreteProductB(); } } }
Strategy pattern
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
using System; namespace DoFactory.GangOfFour.Strategy.Structural { // MainApp test application class MainApp { static void Main() { Context context; // Three contexts following different strategies context = new Context(new ConcreteStrategyA()); context.ContextInterface(); context = new Context(new ConcreteStrategyB()); context.ContextInterface(); context = new Context(new ConcreteStrategyC()); context.ContextInterface(); // Wait for user Console.Read(); } } // "Strategy" abstract class Strategy { public abstract void AlgorithmInterface(); } // "ConcreteStrategyA" class ConcreteStrategyA : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyA.AlgorithmInterface()"); } } // "ConcreteStrategyB" class ConcreteStrategyB : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyB.AlgorithmInterface()"); } } // "ConcreteStrategyC" class ConcreteStrategyC : Strategy { public override void AlgorithmInterface() { Console.WriteLine( "Called ConcreteStrategyC.AlgorithmInterface()"); } } // "Context" class Context { Strategy strategy; // Constructor public Context(Strategy strategy) { this.strategy = strategy; } public void ContextInterface() { strategy.AlgorithmInterface(); } } }
Chain of responsibility
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
using System; namespace DoFactory.GangOfFour.Chain.Structural { // MainApp test application class MainApp { static void Main() { // Setup Chain of Responsibility Handler h1 = new ConcreteHandler1(); Handler h2 = new ConcreteHandler2(); Handler h3 = new ConcreteHandler3(); h1.SetSuccessor(h2); h2.SetSuccessor(h3); // Generate and process request int[] requests = {2, 5, 14, 22, 18, 3, 27, 20}; foreach (int request in requests) { h1.HandleRequest(request); } // Wait for user Console.Read(); } } // "Handler" abstract class Handler { protected Handler successor; public void SetSuccessor(Handler successor) { this.successor = successor; } public abstract void HandleRequest(int request); } // "ConcreteHandler1" class ConcreteHandler1 : Handler { public override void HandleRequest(int request) { if (request >= 0 && request < 10) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } // "ConcreteHandler2" class ConcreteHandler2 : Handler { public override void HandleRequest(int request) { if (request >= 10 && request < 20) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } // "ConcreteHandler3" class ConcreteHandler3 : Handler { public override void HandleRequest(int request) { if (request >= 20 && request < 30) { Console.WriteLine("{0} handled request {1}", this.GetType().Name, request); } else if (successor != null) { successor.HandleRequest(request); } } } }
Visitor pattern
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
using System; using System.Collections; namespace DoFactory.GangOfFour.Visitor.Structural { // MainApp test application class MainApp { static void Main() { // Setup structure ObjectStructure o = new ObjectStructure(); o.Attach(new ConcreteElementA()); o.Attach(new ConcreteElementB()); // Create visitor objects ConcreteVisitor1 v1 = new ConcreteVisitor1(); ConcreteVisitor2 v2 = new ConcreteVisitor2(); // Structure accepting visitors o.Accept(v1); o.Accept(v2); // Wait for user Console.Read(); } } // "Visitor" abstract class Visitor { public abstract void VisitConcreteElementA( ConcreteElementA concreteElementA); public abstract void VisitConcreteElementB( ConcreteElementB concreteElementB); } // "ConcreteVisitor1" class ConcreteVisitor1 : Visitor { public override void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.WriteLine("{0} visited by {1}", concreteElementA.GetType().Name, this.GetType().Name); } public override void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console.WriteLine("{0} visited by {1}", concreteElementB.GetType().Name, this.GetType().Name); } } // "ConcreteVisitor2" class ConcreteVisitor2 : Visitor { public override void VisitConcreteElementA( ConcreteElementA concreteElementA) { Console.WriteLine("{0} visited by {1}", concreteElementA.GetType().Name, this.GetType().Name); } public override void VisitConcreteElementB( ConcreteElementB concreteElementB) { Console.WriteLine("{0} visited by {1}", concreteElementB.GetType().Name, this.GetType().Name); } } // "Element" abstract class Element { public abstract void Accept(Visitor visitor); } // "ConcreteElementA" class ConcreteElementA : Element { public override void Accept(Visitor visitor) { visitor.VisitConcreteElementA(this); } public void OperationA() { } } // "ConcreteElementB" class ConcreteElementB : Element { public override void Accept(Visitor visitor) { visitor.VisitConcreteElementB(this); } public void OperationB() { } } // "ObjectStructure" class ObjectStructure { private ArrayList elements = new ArrayList(); public void Attach(Element element) { elements.Add(element); } public void Detach(Element element) { elements.Remove(element); } public void Accept(Visitor visitor) { foreach (Element e in elements) { e.Accept(visitor); } } } }