Object Oriented Design Patterns Using C#


Simple examples of 23 Gang of Four Design Patterns in C#.

The foundation of many popular software architectures are based on Object-Oriented design patterns introduced by Gangs of Four, in their book "Design Patterns: Elements of Reusable Object-Oriented Software (1994)". The four authors were Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides.

1. Strategy

Strategy patterns are groups of interchangeable functions that can be initialized for different purpose. This can be implemented by using abstract methods or interfaces.

For example we have Fruit class. We can create apple and orange subclasses based on Fruit class and give them different discount algorithms.

public abstract class Fruit
{
    public abstract decimal GetPrice(decimal weight);
}

public class Apple : Fruit
{
    public override decimal GetPrice(decimal weight)
    {
        decimal price = 0;
        if (weight < 10)
        {
            price = 2;
        }
        else
        {
            price = 1.5M;
        }
        return price;
    }
}

public class Orange : Fruit
{
    public override decimal GetPrice(decimal weight)
    {
        decimal price = 0;
        if (weight < 5)
        {
            price = 5;
        }
        else
        {
            price = 3.5M;
        }
        return price;
    }
}

public class PriceChecker
{
    private Fruit _fruit;

    public void SetType(Fruit fruit)
    {
        this._fruit = fruit;
    }

    public decimal GetPrice(decimal weight)
    {
        return _fruit.GetPrice(weight);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        PriceChecker checker = new PriceChecker();

        checker.SetType(new Apple());
        decimal price15Apple = checker.GetPrice(15);
        decimal price8Apple = checker.GetPrice(8);

        checker.SetType(new Orange());
        decimal price10Orange = checker.GetPrice(10);
        decimal price3Oranage = checker.GetPrice(3);
    }
}

2. Decorator

Decorator Pattern is also called wrapper pattern. Without creating subclass, it create a wrapper class with the same interface as another class.

For example, we have a book class with interface IBook, and implement a Comic class wrapper class.

public interface IBook
{
    string GetAuthor();
}

public class Book : IBook
{
    public string GetAuthor()
    {
        //...
    }
}

public class Comic : IBook
{
    IBook _book;

    public Comic(IBook book)
    {
        _book = book;
    }

    public string GetAuthor()
    {
        return _book.GetAuthor();
    }

    public string GetIllustrator()
    {
        //...
    }
}

3. Factory Method

Factory Method provides an interface to create objects in a superclass, but allows a subclass factory to create different type of object.

For example, we have IPerson interface, and class Employee and Customer both implementing IPerson Interface. PersonFactory class will create different classes based on person type.

For example, we have Manager class inherances Employee class. ManagerFactory inherances EmployeeFactory.

public class Employee
{
    //...
}

public class Manager : Employee
{
    //...
}

public class EmployeeFactory
{
    public virtual Employee CreateEmloyee()
    {
        return new Employee();
    }
}

public class ManagerFactory : EmployeeFactory
{
    public override Employee CreateEmloyee()
    {
        return new Manager();
    }
}

4. Observer

A subject can have multiple observer classes. When the subject class attributes changed, it can notify all observer classes. A good example is a UI object can have multiple event handlers. For example, Scheduler class has a list of attendees. When scheduled time changed, it notify all attendees.

public class Attendee
{
    public void Update(DateTime dt)
    {
        //....
    }
}

public class Scheduler
{
    List attendees = new List();

    public void Add(Attendee obj)
    {
        attendees.Add(obj);
    }

    public void ChangeSchedule(DateTime dt)
    {
        //.....
        Notify(dt);
    }

    public void Notify(DateTime dt)
    {
        foreach (Attendee obj in attendees)
        {
            obj.Update(dt);
        }
    }
}

5. Chain of Responsibility

Chain of Responsibility is used when a request need to be processed by a chained of objects. Without needs to know each objects, the request will be passed to a handler, the handler will pass the request along the chain until the process is finished.

For example of order fulfillment. A request is passed to a handler to go through different steps: Receiving the order, distribute the order to a factory, ship the product, bill the customer.

public interface IOrder
{
    //...
}

public class Process
{
    protected Process nextProcess = null;
    protected IOrder _order;

    public Process(IOrder order)
    {
        _order = order;
    }

    public void SetNextProcess(Process next)
    {
        nextProcess = next;
    }

    public void ProcessOrder()
    {
        //....

        if (nextProcess != null)
        {
            nextProcess.ProcessOrder();
        }
    }
}

public class Receiving : Process
{
    public Receiving(IOrder order):base(order)
    {
        //...
    }
}

public class Distributing : Process
{
    public Distributing(IOrder order):base(order)
    {
        //...
    }
}

public class Shipping : Process
{
    public Shipping(IOrder order) : base(order)
    {
        //...
    }
}

public class Billing : Process
{
    public Billing(IOrder order) : base(order)
    {
        //...
    }
}

public class OrderFulfillment
{
    public void Fulfillment(IOrder order)
    {
        Receiving rec = new Receiving(order);
        Distributing dis = new Distributing(order);
        Shipping ship = new Shipping(order);
        Billing bill = new Billing(order);

        rec.SetNextProcess(dis);
        dis.SetNextProcess(ship);
        ship.SetNextProcess(bill);

        rec.ProcessOrder();
    }
}

6. Singleton

Singleton is used when a class can only have a single instance and shared among all requests. For example connection pool, cache, global variables.

Singleton class needs to be sealed to prevent inheriance, having private (or hidden) constructor to avoid instance to be created. A lock needs to be placed to make it thread safe when creating the object.

public sealed class Cache
{
    private static volatile Cache instance;
    private static object lockObject = new Object();
    private Cache() { }

    public static Cache CacheObject
    {
        get
        {
            if (instance == null)
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        InitializeInstance();
                    }
                }
            }
            return instance;
        }
    }

    private static void InitializeInstance()
    {
        instance = new Cache();
    }
}
       

Singleton is static, to use it as a parent class to create singleton subclasses, you need to use generic. Please reference Singleton pattern in parent class using C#

7. Flyweight

Flyweight is used to saving memory by creating shared objects with intrinsic state. Extrinsic states are passed in as dynamic parameters when needed.

Flyweight pattern has a factory class to hold shared objects and return an object when requested. Flyweight is the interface for all shared objects. ConcreteFlyweight is the class implementing the interface.

For example, Flyweight can be used in a game software to creating balls and cubes with different colors.

public class ShapeFactory
{
    private Hashtable _flyweights = new Hashtable();

    public IShape GetShape(string key)
    {
        if (_flyweights.Contains(key))
        {
            return _flyweights[key] as IShape;
        }
        else
        {
            IShape newFlyweight = null;
            if ("Ball".Equals(key))
            {
                newFlyweight = new Ball();
            }else if ("Cube".Equals(key))
            {
                newFlyweight = new Cube();
            }
            _flyweights.Add(key, newFlyweight);
            return newFlyweight;
        }

    }
}

public interface IShape
{
    void Draw(Color o);
}

public class Ball : IShape
{
    public void Draw(Color o)
    {
        //...
    }
}

public class Cube : IShape
{
    public void Draw(Color o)
    {
        //...
    }
}

8. Adapter

When a client have a interface not compatible with an adaptee class, an adapter class is created to convert the adaptee interface to the client interface so the client can use the adaptee. Use cases can be a hardware driver, or integrating a third party libary.

public class Client
{
    private IRequest _request;

    public Client(IRequest request)
    {
        _request = request;
    }

    public void MakeRequest()
    {
        _request.Print();
    }
}

public interface IRequest
{
    void Print();
}

public class Adapter : Adaptee, IRequest
{
    public void Print()
    {
        PrinterSetup();
        PrintOutput();
    }
}

public class Adaptee
{
    public void PrinterSetup()
    {
        //...
    }

    public void PrintOutput()
    {
        //...
    }
}
       

9. Facade

Provide a single interface to a set of interfaces, to hide the complicity of the system and make it easy to use.

public class A
{
    public bool CheckAccountStatus(int accountNo)
    {
        //....
    }
}

public class B
{
    public bool WithDraw(int accountNo, decimal amount)
    {
        //....
    }
}

public class C
{
    public bool Reject(int accountNo)
    {
        //....
    }
}

public class Facade
{
    A a = new A();
    B b = new B();
    C c = new C();

    public bool WithDraw(int accountNo, decimal amount)
    {
        if(a.CheckAccountStatus(accountNo, amount))
        {
            b.WithDraw(accountNo, amount);
        }
        else
        {
            c.Reject(accountNo);
        }
    }
}
       

10. Template

Template define a skeleton of an algorithm in an operation, lets subclasses redefine certain steps without changing the algorithms structure.

For example, there's same steps to get checking and saving account interest rate, but different algorithms.

public abstract class AccountBase
{
    public void GetInterest(int accountNo)
    {
        OperationA(accountNo);
        OperationB(accountNo);
        OperationC(accountNo);
    }
    public bool OperationA(int accountNo)
    {
        //....
    }
    public abstract bool OperationB(int accountNo);
    public abstract bool OperationC(int accountNo);
}

public abstract class Saving: AccountBase
{
    public override bool OperationB(int accountNo)
    {
        //...
    }
    public override bool OperationC(int accountNo)
    {
        //...
    }
}

public abstract class Checking : AccountBase
{
    public override bool OperationB(int accountNo)
    {
        //...
    }
    public override bool OperationC(int accountNo)
    {
        //...
    }
}

11. Builder

Builder pattern uses an interface class to separate the construction processes of a complex object from its representation so that the same construction processes can create different representations.

Builder pattern includes 4 parts: a builder interface, a concrete builder, a director and a product.

public class Jet
{
    public Object Wings { get; set; }
    public Object Body { get; set; }
    public Object Engines { get; set; }
}

public interface IJetBuilder
{
    void BuildWings();
    void BuildBody();
    void InstallEngine();
    Jet GetJet();
}

public class ComercialJetBuilder : IJetBuilder
{
    Jet _jet;

    ComercialJetBuilder()
    {

    }
    public void BuildWings()
    {
        //...
    }
    public void BuildBody()
    {
        //...
    }
    public void InstallEngine()
    {
        //...
    }

    public  Jet GetJet()
    {
        return _jet;
    }
}

public class BusinessJetBuilder : IJetBuilder
{
    Jet _jet;

    BusinessJetBuilder()
    {

    }
    public void BuildWings()
    {
        //...
    }
    public void BuildBody()
    {
        //...
    }
    public void InstallEngine()
    {
        //...
    }

    public Jet GetJet()
    {
        return _jet;
    }
}

public class JetBuildDirector
{
    public void Construct(IJetBuilder builder)
    {
        builder.BuildBody();
        builder.BuildWings();
        builder.InstallEngine();
    }
}

12. Iterator

Iterator pattern provides an interface to traverse a list of items within a container.

Iterator pattern contains iterator interface, concrete iterator, container abstract and concrete container.

For example we can create an iterator to traverse a list in forward order.

abstract class Container
{
    public abstract ForwardIterator CreateIterator();
}

class MyContainer : Container
{
    private ArrayList _items = new ArrayList();

    public override ForwardIterator CreateIterator()
    {
        return new MyIterator(this);
    }

    public int Count
    {
        get { return _items.Count; }
    }

    // Indexer
    public object this[int index]
    {
        get { return _items[index]; }
        set { _items.Add(value); }
    }
}

abstract class ForwardIterator
{
    public abstract object Next();
}

class MyIterator : ForwardIterator
{
    private MyContainer _container;
    private int _current = -1;

    public MyIterator(MyContainer container)
    {
        this._container = container;
    }

    public override object Next()
    {
        object ret = null;
        if (_current < _container.Count - 1)
        {
            ret = _container[++_current];
        }

        return ret;
    }
}

13. Composite

Compose pattern represent hierarchies. Composite client using composite interface to access childen and parent nodes in a similar manor.

For example, the hierarchy of employees and managers in an organization.

public interface IEmployee
{
    int EmployeeID { get; set; }
    string Name { get; set; }
    decimal Commission { get; set; }
}

public class Employee : IEmployee
{
    public int EmployeeID { get; set; }
    public string Name { get; set; }
    public decimal Commission { get; set; }
}

public class Supervisor : IEmployee
{
    public int EmployeeID { get; set; }
    public string Name { get; set; }
    public decimal Commission { get; set; }

    public List ListMemebers = new List();

    public decimal GetDepartmentCommission()
    {
        decimal commission = this.Commission;
        foreach(IEmployee employee in ListMemebers)
        {
            if(employee.GetType() == typeof(Supervisor))
            {
                commission += ((Supervisor)employee).GetDepartmentCommission();
            }
            else
            {
                commission += employee.Commission;
            }
        }
        return commission;
    }

    public void AddMember(IEmployee employee)
    {
        ListMemebers.Add(employee);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Employee e1 = new Employee { EmployeeID = 1, Name = "Emp 1", Commission = 3.1M };
        Employee e2 = new Employee { EmployeeID = 2, Name = "Emp 2", Commission = 4 };
        Employee e3 = new Employee { EmployeeID = 3, Name = "Emp 3", Commission = 5 };
        Employee e4 = new Employee { EmployeeID = 4, Name = "Emp 4", Commission = 3.2M };
        Employee e5 = new Employee { EmployeeID = 5, Name = "Emp 5", Commission = 4 };
        Employee e6 = new Employee { EmployeeID = 6, Name = "Emp 6", Commission = 5.9M };

        Supervisor e7 = new Supervisor { EmployeeID = 7, Name = "Emp 7", Commission = 6 };
        Supervisor e8 = new Supervisor { EmployeeID = 7, Name = "Emp 8", Commission = 8.5M };

        Supervisor e9 = new Supervisor { EmployeeID = 7, Name = "Emp 9", Commission = 10 };

        e7.AddMember(e1);
        e7.AddMember(e2);
        e7.AddMember(e3);

        e8.AddMember(e4);
        e8.AddMember(e5);
        e8.AddMember(e6);

        e9.AddMember(e7);
        e9.AddMember(e8);

        decimal totalMemberCommission = e9.GetDepartmentCommission();
    }
}

14. Command

Command pattern encapsulate commands as objects. Command classes can wrap different receivers to process requests. Receivers can invokes different Commands with parameters.

For example, command pattern can be used for query and update database.

public class Program
{
    public static void Main()
    {
        Invoker invoker = new Invoker();
        Receiver receiver = new Receiver();

        QueryCommand command1 = new QueryCommand(receiver);
        invoker.Command = command1;
        command1.Parameters.Add("p1");
        command1.Parameters.Add("p2");
        dynamic result = invoker.ExecuteCommand();

        decimail x = 10;
        UpdateCommand command2 = new UpdateCommand(receiver);
        invoker.Command = command2;
        command2.Parameters.Add(result.r1 + x);
        command2.Parameters.Add(result.r2);
        invoker.ExecuteCommand();
    }
}

public class Receiver
{
    public void Update(List parameters)
    {
        //update database
    }

    public void Query(List parameters)
    {
        //query database
    }
}

public class Invoker
{
    public ICommand Command { get; set; }

    public dynamic ExecuteCommand()
    {
        object ret = null;
        //...
        Command.Execute();
        return ret;
    }
}

public interface ICommand
{
    void Execute();
}

public class UpdateCommand : ICommand
{
    protected Receiver _receiver;
    public List Parameters { get; set; }

    public UpdateCommand(Receiver receiver)
    {
        _receiver = receiver;
    }

    public void Execute()
    {
        _receiver.Update(Parameters);
    }
}

public class QueryCommand : ICommand
{
    protected Receiver _receiver;
    public List Parameters { get; set; }

    public QueryCommand(Receiver receiver)
    {
        _receiver = receiver;
    }

    public void Execute()
    {
        _receiver.Query(Parameters);
    }
}

15. Mediator

A moderator class encapsulates a set of objects. So the objects do not interact with each other directly.

For example, create a moderator to convert data from database to the format to display.

class MainApp
{
    static void Main()
    {
        Mediator mediator = new Mediator();

        View view = new View(mediator);
        Model model = new Model(mediator);
        model.Amount = 7890013.2M;

        mediator.MyView = view;
        mediator.MyModel = model;

        mediator.ConvertAmount();

        Console.WriteLine(view.Amount);
    }
}

public class Mediator
{
    public View MyView { get; set; }
    public Model MyModel { get; set; }

    public void ConvertAmount()
    {
        MyView.Amount = $"Hello, your amount is {MyModel.Amount: C}";
    }
}

public class View
{
    public string Amount { get; set; }
    protected Mediator mediator;

    public View(Mediator mediator)
    {
        this.mediator = mediator;
    }
}

public class Model
{
    public decimal Amount { get; set; }
    protected Mediator mediator;

    public Model(Mediator mediator)
    {
        this.mediator = mediator;
    }
}

16. State

State pattern create an object to changed beheviour depends on its state.

For example, there're a few processes to handle before it completes.

class MainApp
{
    static void Main()
    {
        Context c = new Context(new State(8));

        bool finished = false;
        do
        {
            finished = c.Request();
        } while (!finished);
    }
}

class State
{
    public int _status { get; set; }

    public State(int status)
    {
        _status = status;
    }

    public bool Handle(Context context)
    {
        bool finished = false;
        if (_status <= 0)
        {
            finished = true;
        }
        else
        {
            switch (_status)
            {
                //Process
                default:
                    break;
            }
            _status--;
            context.State = new State(_status);
        }

        return finished;
    }
}

class Context
{
    private State _state;

    public Context(State state)
    {
        this.State = state;
    }

    // Gets or sets the state

    public State State
    {
        get { return _state; }
        set
        {
            //log or alert, etc
            _state = value;
        }
    }

    public bool Request()
    {
        return _state.Handle(this);
    }
}

17. Proxy

A proxy is a wrapper that is being called by the client to access other objects or resources.

    interface ICar
{
    void DriveCar();
}

public class Car : ICar
{
    public void DriveCar()
    {
        //...
    }
}

public class ProxyCar
{
    private Driver driver;
    private ICar realCar;

    public ProxyCar(Driver driver)
    {
        this.driver = driver;
        this.realCar = new Car();
    }

    public bool Drive()
    {
        bool ok = true;
        if (driver.CanDrive())
        {
            this.realCar.DriveCar();
        }
        else
        {
            ok = false;
        }
        return ok;
    }
}

public interface IDriver
{
    bool CanDrive();
}

public class Driver:IDriver
{
    public bool Lisensed { get; set; }
    public bool FitToDrive { get; set; }

    public Driver(bool licensed, bool fit)
    {
        Lisensed = licensed;
        FitToDrive = fit;
    }

    public bool CanDrive()
    {
        return Lisensed & FitToDrive;
    }
}

class Program
{
    static void Main()
    {
        bool ok = false;

        ProxyCar car = new ProxyCar(new Driver(true, true));
        ok = car.Drive();

        car = new ProxyCar(new Driver(true, false));
        ok = car.Drive();
    }
}

18. Abstract Factory

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

For example, we have IPerson interface, and class Employee and Customer both implementing IPerson Interface. PersonFactory class will create different classes based on person type.

public class Employee : IPerson
{
    //...
}

public class Customer : IPerson
{
    //...
}

public class PersonFactory
{
    public IPerson GetPerson(int type)
    {
        if (type == 1)
        {
            return new Employee();
        }
        else
        {
            return new Customer();
        }
    }
}

19. Bridge

Bridge pattern is used to separate the interface of a class from the implementation details, so the underline class can change without affacting the clicent calling the class.

public interface IShare
{
    void Send();
}

public class Email : IShare
{
    public void Send()
    {
        //Send email
    }
}

public class Message : IShare
{
    public void Send()
    {
        //Send SMS message
    }
}

class Abstraction
{
    protected IShare implementor;

    // Property
    public IShare Implementor
    {
        set { implementor = value; }
    }

    public virtual void Send()
    {
        implementor.Send();
    }
}

class MainApp
{
    static void Main()
    {
        Abstraction ab = new Abstraction();

        // Set implementation and call
        ab.Implementor = new Email();
        ab.Send();

        // Change implemention and call
        ab.Implementor = new Message();
        ab.Send();
    }
}

20. Interpreter

Interpreter define a representation for its grammar along with an interpreter that uses the representation to interpret sentences.

For example, we can create an interpreter to output a person's profile

public class Context
{
    public string Output { get; set; }
}

public interface IExpression
{
    void Interpret(Context context);
}

public class Hobby: IExpression
{
    public string Hobbies { get; set; }

    public Hobby(string hobbies)
    {
        Hobbies = hobbies;
    }

    public void Interpret(Context context)
    {
        context.Output += string.Format("Hobbies: {0} ", Hobbies);
    }
}

public class Family : IExpression
{
    public string Families { get; set; }

    public Family(string hobbies)
    {
        Families = hobbies;
    }

    public void Interpret(Context context)
    {
        context.Output += string.Format("Families: {0} ", Families);
    }
}

public class Career : IExpression
{
    public string Careers { get; set; }

    public Career(string career)
    {
        Careers = career;
    }

    public void Interpret(Context context)
    {
        context.Output += string.Format("Career: {0} ", Careers);
    }
}

public class Person : IExpression
{
    public string Name { get; set; }
    public string Hobbies { get; set; }
    public string Families { get; set; }
    public string Careers { get; set; }

    public Person(string name, string hobbies, string family, string career)
    {
        this.Name = name;
        this.Hobbies = hobbies;
        this.Families = family;
        this.Careers = career;
    }

    public void Interpret(Context context)
    {
        context.Output += $"Profile for {Name}\r\n";
        context.Output += $"{Careers}\r\n";
        context.Output += $"{Families}\r\n";
        context.Output += $"{Hobbies}\r\n";
    }
}

21. Memento

Memento save and get an object's internal state so that the object can be restored to this state later.

For example, we simulating an installer installs 3 software and restore back to intial state.

class State
{
    private string state;

    public void Set(string state)
    {
        this.state = state;
    }

    public Memento Save()
    {
        return new Memento(state);
    }

    public void Restore(Memento memento)
    {
        state = memento.SavedState;
    }

    public class Memento
    {
        public readonly string SavedState;

        public Memento(string state)
        {
            SavedState = state;
        }
    }
}

class Installer
{
    static void Main(string[] args)
    {
        List savedStates = new List();

        State state = new State();
        state.Set("initial");
        //install software 1
        state.Set("s1");
        savedStates.Add(state.Save());
        //install software 2
        state.Set("s2");
        savedStates.Add(state.Save());
        //install software 1
        state.Set("s3");
        //restore to initial
        state.Restore(savedStates[0]);
    }
}

22. Prototype

Prototype pattern defines a prototype class. And new objects can be created by copying this prototype.

public interface IPrototype
{
    IPrototype Clone();
}

public class PrototypeA : IPrototype
{
    public IPrototype Clone()
    {
        return (IPrototype)this.Clone();
    }
}

public class PrototypeB : IPrototype
{
    public IPrototype Clone()
    {
        return (IPrototype)this.Clone();
    }
}

23. Visitor

Visitor pattern represents an operation to be performed on the child elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

For example, a park can add new viewpoints without modifying visitor class.

class MainApp
{
    static void Main()
    {
        Park park = new Park();
        park.Add(new Mountain());
        park.Add(new Spring());
        park.Add(new Playground());

        Visitor visitor1 = new VisitorA();
        Visitor visitor2 = new VisitorB();

        park.Accept(visitor1);
        park.Accept(visitor2);
    }
}

public interface Visitor
{
    void Visit(Mountain element);
    void Visit(Spring element);
    void Visit(Playground element);
}

public class VisitorA : Visitor
{
    public void Visit(Mountain element)
    {
        Print(element);
    }

    public void Visit(Spring element)
    {
        Print(element);
    }

    public void Visit(Playground element)
    {
        Print(element);
    }

    private void Print(ViewPoint viewpoint)
    {
        Console.WriteLine("{0} visited by {1}", viewpoint.Name, this.GetType().Name);
    }
}

public class VisitorB : Visitor
{
    public void Visit(Mountain element)
    {
        Print(element);
    }

    public void Visit(Spring element)
    {
        Print(element);
    }

    public void Visit(Playground element)
    {
        Print(element);
    }

    private void Print(ViewPoint viewpoint)
    {
        Console.WriteLine("{0} visited by {1}", viewpoint.Name, this.GetType().Name);
    }
}

public abstract class ViewPoint
{
    public string Name { get; set; }

    public abstract void Accept(Visitor visitor);
}

public class Mountain : ViewPoint
{
    public Mountain()
    {
        Name = "Mountain";
    }

    public override void Accept(Visitor visitor)
    {
        visitor.Visit(this);
    }

    public void OperationA()
    {
    }
}

public class Spring : ViewPoint
{
    public Spring()
    {
        Name = "Spring";
    }

    public override void Accept(Visitor visitor)
    {
        visitor.Visit(this);
    }

    public void OperationB()
    {
    }
}

public class Playground : ViewPoint
{
    public Playground()
    {
        Name = "Playground";
    }

    public override void Accept(Visitor visitor)
    {
        visitor.Visit(this);
    }

    public void OperationB()
    {
    }
}

class Park
{
    private List _elements = new List();

    public void Add(ViewPoint element)
    {
        _elements.Add(element);
    }

    public void Remove(ViewPoint element)
    {
        _elements.Remove(element);
    }

    public void Accept(Visitor visitor)
    {
        foreach (ViewPoint element in _elements)
        {
            element.Accept(visitor);
        }
    }
}

If you need more details of each design pattern, you can visit sourcemaking.com. It has source code for different programming languages including Java, C++, PHP, Delphi and Python.