GoFのデザインパターン23種類をC#で書いたまとめ記事です。
本記事はGang of Fourの「オブジェクト指向における再利用のためのデザインパターン」で紹介されている23種類のデザインパターンを参考に、最小構成のC#サンプルコードを列挙しています。
どのデザインパターンを適用するか悩んだ際など、自由にご利用ください。
なお免責として、自分の理解の範囲なので悪しからず。内容に関する指摘は歓迎です。
デザインパターンと直接関係していないクラスや関数・変数に関しては、Some~, Hoge, Foo等の言葉を用いて表しています。
http://amazon.co.jp/オブジェクト指向における再利用のためのデザインパターン-エリック-ガンマ/dp/4797311126amazon.co.jp
GitHubで見たい方はこちら。
Abstract Factory
Factory
public abstract class AbstractFactory
{
public abstract Product CreateProduct();
}
public class ConcreteFactory1 : AbstractFactory
{
public override Product CreateProduct()
{
return new ProductA();
}
}
public class ConcreteFactory2 : AbstractFactory
{
public override Product CreateProduct()
{
return new ProductB();
}
}
Product
public abstract class Product
{
}
public class ProductA : Product
{
}
public class ProductB : Product
{
}
Some Application
public class SomeApplication
{
private Product product;
public void Init(AbstractFactory factory)
{
this.product = factory.CreateProduct();
}
}
public class SomeApplicationUser
{
public void SomeFunction(bool someCondition)
{
var someApp = new SomeApplication();
if (someCondition)
{
var factory1 = new ConcreteFactory1();
someApp.Init(factory1);
}
else
{
var factory2 = new ConcreteFactory2();
someApp.Init(factory2);
}
}
}
Builder
Result
public class Result
{
public void AddFoo()
{
}
public void RemoveFoo()
{
}
public void SetBar(int someParam)
{
}
}
Builder
public abstract class Builder
{
public abstract void BuildPartA();
public abstract void BuildPartB();
public abstract void BuildPartC();
public abstract Result GetResult();
}
public class ConcreteBuilder : Builder
{
private Result result = null;
public ConcreteBuilder()
{
this.result = new Result();
}
public override void BuildPartA()
{
this.result.AddFoo();
}
public override void BuildPartB()
{
this.result.AddFoo();
this.result.SetBar(0);
}
public override void BuildPartC()
{
this.result.RemoveFoo();
this.result.SetBar(1);
}
public override Result GetResult()
{
return result;
}
}
Director
public class Director
{
public void Construct(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
}
public void ConstructHoge(Builder builder)
{
builder.BuildPartB();
builder.BuildPartC();
}
public void ConstructHuga(Builder builder)
{
builder.BuildPartA();
builder.BuildPartB();
builder.BuildPartC();
}
}
Some Application
public class SomeApplication
{
public void SomeFunction(int someCondition)
{
var builder = new ConcreteBuilder();
var director = new Director();
switch (someCondition)
{
case 1:
director.Construct(builder);
break;
case 2:
director.ConstructHoge(builder);
break;
case 3:
director.ConstructHuga(builder);
break;
}
var result = builder.GetResult();
}
}
Factory Method
・抽象クラスが、具象クラスによって決定されるインスタンスに興味がないとき
・具象クラスにインスタンスを作らせ、抽象クラスではそのインタフェース(抽象クラス)のみを扱う
最もシンプルな実装
Product
public abstract class Product
{
}
public class ProductA : Product
{
}
public class ProductB : Product
{
}
Product User
public abstract class ProductUser
{
private Product product = null;
protected abstract Product CreateProduct();
public ProductUser()
{
}
public void LazyInit()
{
this.product = CreateProduct();
}
public void SomeFunction()
{
}
}
public class ConcreteProductUser1 : ProductUser
{
protected override Product CreateProduct()
{
return new ProductA();
}
}
public class ConcreteProductUser2 : ProductUser
{
protected override Product CreateProduct()
{
return new ProductB();
}
}
Some Application
public class SomeApplication
{
public void SomeFunction(bool someCondition)
{
if (someCondition)
{
var user1 = new ConcreteProductUser1();
user1.LazyInit();
user1.SomeFunction();
}
else
{
var user2 = new ConcreteProductUser2();
user2.LazyInit();
user2.SomeFunction();
}
}
}
テンプレートを使う場合
public class StandartProductUser<T> : ProductUser where T : Product, new()
{
protected override Product CreateProduct()
{
return new T();
}
}
public class SomeApplication
{
public void SomeFunction(bool someCondition)
{
if (someCondition)
{
var user1 = new StandartProductUser<ProductA>();
user1.LazyInit();
user1.SomeFunction();
}
else
{
var user2 = new StandartProductUser<ProductB>();
user2.LazyInit();
user2.SomeFunction();
}
}
}
Prototype
Product
public class Product
{
public void Init(int someParam)
{
}
public virtual Product Clone()
{
return (Product)MemberwiseClone();
}
}
public class ProductB : Product
{
public override Product Clone()
{
return (Product)MemberwiseClone();
}
}
Prototype Factory
public class PrototypeFactory
{
private Product prototypeProduct = null;
public PrototypeFactory(Product prototype)
{
this.prototypeProduct = prototype;
}
public Product MakeProduct1()
{
var product = this.prototypeProduct.Clone();
product.Init(1);
return product;
}
public Product MakeProduct2()
{
var product = this.prototypeProduct.Clone();
product.Init(2);
return product;
}
}
Some Application
public class SomeApplication
{
public void SomeFunction(bool someCondition)
{
Product prototype;
if (someCondition)
{
prototype = new Product();
}
else
{
prototype = new ProductB();
}
var factory = new PrototypeFactory(prototype);
var product1 = factory.MakeProduct1();
var product2 = factory.MakeProduct2();
}
}
Singleton
public class Singleton
{
private static Singleton instance = null;
public static Singleton Instance
{
get
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
protected Singleton()
{
}
}
Adapterパターン
- 既存クラスを利用したいが、インタフェースが合わない
Class Adapter
public class Adaptee
{
public void HugaFunction()
{
}
}
public interface Target
{
public void HogeFunction();
}
public class Adapter : Adaptee, Target
{
public void HogeFunction()
{
this.HogeFunction();
}
}
Object Adapter
public class Adaptee
{
public void HugaFunction()
{
}
}
public class Target
{
public virtual void HogeFunction()
{
}
}
public class Adapter : Target
{
private Adaptee adaptee = null;
public Adapter(Adaptee adaptee)
{
this.adaptee = adaptee;
}
public override void HogeFunction()
{
adaptee.HugaFunction();
}
}
Bridge
- ネストされた継承を解消したい
- 実装の変更に依存させない
- 実装をサブクラスの追加により拡張可能にすべき
Implementor
public abstract class Implementor
{
public abstract void SomeFunctionImp();
}
public class ConcreteImplementorA : Implementor
{
public override void SomeFunctionImp()
{
}
}
public class ConcreteImplementorB : Implementor
{
public override void SomeFunctionImp()
{
}
}
Abstraction
public abstract class Abstraction
{
private Implementor imp = null;
public Abstraction(Implementor implementor)
{
this.imp = implementor;
}
public void SomeFunction()
{
this.imp.SomeFunctionImp();
}
}
public class RefinedAbstraction : Abstraction
{
public RefinedAbstraction(Implementor implementor) : base(implementor)
{
}
public void SomeRefinedFunction()
{
SomeFunction();
SomeFunction();
}
}
Composite
Component
public abstract class Component
{
public virtual void Add(Component component)
{
}
public virtual void Remove(Component component)
{
}
public virtual Component GetChild(int index)
{
return null;
}
public abstract void Operation();
}
Composite, Leaf
using System.Collections.Generic;
public class Composite : Component
{
private List<Component> children = null;
public Composite()
{
this.children = new List<Component>();
}
public override void Add(Component component)
{
children.Add(component);
}
public override void Remove(Component component)
{
children.Remove(component);
}
public override Component GetChild(int index)
{
if (index < children.Count)
{
return children[index];
}
return null;
}
public override void Operation()
{
foreach (var child in children)
{
child.Operation();
}
}
}
public class Leaf : Component
{
public override void Operation()
{
}
}
Decorator
Component
public abstract class Component
{
public abstract void Operation();
}
public class ConcreteComponent : Component
{
public override void Operation()
{
}
}
Decorator
public abstract class Decorator : Component
{
private Component component;
public Decorator(Component component)
{
this.component = component;
}
public override void Operation()
{
component.Operation();
}
}
public class ConcreteDecoratorA : Decorator
{
private int someParam;
public ConcreteDecoratorA(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();
}
}
public class ConcreteDecoratorB : Decorator
{
public ConcreteDecoratorB(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();
SomeFunction();
}
public void SomeFunction()
{
}
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
Component comp = new ConcreteComponent();
Component deco1 = new ConcreteDecoratorA(comp);
Component deco2 = new ConcreteDecoratorB(comp);
Component deco3 = new ConcreteDecoratorA(new ConcreteDecoratorB(comp));
Component deco4 = new ConcreteDecoratorA(new ConcreteDecoratorB(new ConcreteDecoratorB(comp)));
}
}
Facade
・サブシステムの構成要素を隠ぺい及び結合を弱める
Facade
using SomeSubSystems;
public class Facade
{
public void SomeFunction()
{
var subSystemA = new SubSystemA();
var subSystemB = new SubSystemB();
var subSystemC = new SubSystemC();
subSystemA.FunctionA();
subSystemB.FunctionB();
subSystemC.FunctionC();
}
}
namespace SomeSubSystems
{
public class SubSystemA
{
public void FunctionA()
{
}
}
public class SubSystemB
{
public void FunctionB()
{
}
}
public class SubSystemC
{
public void FunctionC()
{
}
}
}
Flyweight
public abstract class Flyweight
{
public abstract void Operation(ExtrinsicState extrinsicState);
}
public class ConcreteFlyweight : Flyweight
{
private int someIntrinsicState;
public override void Operation(ExtrinsicState extrinsicState)
{
}
}
public class UnsharedConcreteFlyweight : Flyweight
{
private int allState;
public override void Operation(ExtrinsicState extrinsicState)
{
}
}
ExtrinsicState
public class ExtrinsicState
{
public int someParam;
}
FlyweightFactory
using System.Collections.Generic;
public class FlyweightFactory
{
private Dictionary<string, ConcreteFlyweight> flyweights;
public FlyweightFactory()
{
flyweights = new Dictionary<string, ConcreteFlyweight>();
}
public ConcreteFlyweight CreateConcreteFlyweight(string key)
{
if (!flyweights.ContainsKey(key))
{
flyweights.Add(key, new ConcreteFlyweight());
}
return flyweights[key];
}
public UnsharedConcreteFlyweight CreateUnsharedConcreteFlyweight()
{
return new UnsharedConcreteFlyweight();
}
}
Some Application
public class SomeApplication
{
public void SomeFuncition()
{
var factory = new FlyweightFactory();
var exState = new ExtrinsicState();
for (int i = 0; i < 100; i++)
{
var concreteFlyweight = factory.CreateConcreteFlyweight("foo");
exState.someParam = i;
concreteFlyweight.Operation(exState);
}
for (int i = 0; i < 30; i++)
{
var concreteFlyweight = factory.CreateConcreteFlyweight("bar");
exState.someParam = i;
concreteFlyweight.Operation(exState);
}
var unsharedFlyweight = factory.CreateUnsharedConcreteFlyweight();
unsharedFlyweight.Operation(exState);
}
}
Proxy
Subject
public abstract class Subject
{
public abstract void Request();
}
public class RealSubject : Subject
{
public override void Request()
{
}
}
public class Proxy : Subject
{
RealSubject realSubject = null;
public override void Request()
{
realSubject.Request();
}
}
Chain of Responsibility
・受け手を明確にせずに、複数あるオブジェクトの1つに対して要求を発行したい
Handler
public abstract class Handler
{
protected Handler successor;
public virtual void HandleRequest()
{
if (successor != null)
{
successor.HandleRequest();
}
}
}
public class ConcreteHandler1 : Handler
{
public override void HandleRequest()
{
base.HandleRequest();
}
}
public class ConcreteHandler2 : Handler
{
public override void HandleRequest()
{
System.Console.WriteLine("some customized handle");
}
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
var handler1 = new ConcreteHandler1();
var handler2 = new ConcreteHandler2();
handler1.HandleRequest();
}
}
Command
Command
public abstract class Command
{
public abstract void Execute();
}
public class ConcreteCommand : Command
{
private int someState;
Receiver receiver = null;
public ConcreteCommand(Receiver receiver)
{
this.receiver = receiver;
}
public override void Execute()
{
receiver.SomeAction();
}
}
Receiver
public class Receiver
{
public void SomeAction()
{
}
}
public class SomeApplication
{
private List<Command> commandList = null;
private int currentIndex = 0;
public void SomeFunction()
{
this.commandList = new List<Command>();
var receiver1 = new Receiver();
var command1 = new ConcreteCommand(receiver1);
commandList.Add(command1);
var receiver2 = new Receiver();
var command2 = new ConcreteCommand(receiver2);
commandList.Add(command2);
}
public void ExecuteNext()
{
commandList[currentIndex].Execute();
currentIndex++;
}
}
Interpreter
using System;
public abstract class AbstractExpression
{
public abstract void Interpret(Context context);
}
public class TerminalExpression : AbstractExpression
{
private string literal;
public TerminalExpression(string literal)
{
this.literal = literal;
}
public override void Interpret(Context context)
{
Console.Write(this.literal);
}
}
public class NonterminalExpression : AbstractExpression
{
private TerminalExpression exp1;
private TerminalExpression exp2;
public NonterminalExpression(TerminalExpression exp1, TerminalExpression exp2)
{
this.exp1 = exp1;
this.exp2 = exp2;
}
public override void Interpret(Context context)
{
Console.Write(this.exp1 + "&" + this.exp2);
}
}
Context
public class Context
{
public string SomeInfo;
}
Client
public class Client
{
public void SomeFunction()
{
var terminalExp1 = new TerminalExpression("literal1");
var terminalExp2 = new TerminalExpression("literal2");
var someExp = new NonterminalExpression(terminalExp1, terminalExp2);
var context = new Context { SomeInfo = "someINfo" };
someExp.Interpret(context);
}
}
Aggregate
public abstract class Aggregate
{
public abstract Iterator CreateIterator();
}
public class ConcreteAggregate : Aggregate
{
public override Iterator CreateIterator()
{
return new ConcreteIterator(this);
}
}
Iterator
public abstract class Iterator
{
protected Aggregate aggregate;
public Iterator(Aggregate aggregate)
{
this.aggregate = aggregate;
}
public abstract void First();
public abstract void Next();
public abstract bool IsDone();
public abstract SomeItem CurrentItem();
}
public class ConcreteIterator : Iterator
{
private int currentIndex = 0;
public ConcreteIterator(Aggregate aggregate) : base(aggregate)
{
}
public override void First()
{
this.currentIndex = 0;
}
public override void Next()
{
this.currentIndex++;
}
public override bool IsDone()
{
return this.currentIndex < aggregate.Count;
}
public override SomeItem CurrentItem()
{
return this.currentIndex[currentIndex];
}
}
SomeApplication
public class SomeItem
{
}
public class SomeApplication
{
private Aggregate someAggregate = null;
public void SomeFunction()
{
var iterator = this.someAggregate.CreateIterator();
iterator.First();
while (!iterator.IsDone())
{
iterator.Next();
var item = iterator.CurrentItem();
}
}
}
Mediator
public abstract class Mediator
{
public abstract void CreateColleagues();
public abstract void ColleagueChanged(Colleague colleague);
}
public class ConcreteMediator : Mediator
{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public override void CreateColleagues()
{
this.colleague1 = new ConcreteColleague1(this);
this.colleague2 = new ConcreteColleague2(this);
}
public override void ColleagueChanged(Colleague colleague)
{
if (colleague == this.colleague1)
{
this.colleague1.SetFoo();
}
else if (colleague == this.colleague2)
{
this.colleague2.SetBar();
}
}
}
Colleague
public abstract class Colleague
{
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
protected void Changed()
{
this.mediator.ColleagueChanged(this);
}
}
public class ConcreteColleague1 : Colleague
{
public ConcreteColleague1(Mediator mediator) : base(mediator)
{
}
public void HogeEvent()
{
Changed();
}
public void SetFoo()
{
}
}
public class ConcreteColleague2 : Colleague
{
public ConcreteColleague2(Mediator mediator) : base(mediator)
{
}
public void HugaEvent()
{
Changed();
}
public void SetBar()
{
}
}
Some Application
public class SomeApplication
{
public void SomeFunction()
{
var mediator = new ConcreteMediator();
mediator.CreateColleagues();
}
}
Memento
- カプセル化を破壊せずに、ある時点のスナップショットを残しておき、後に復元等で利用する
Memento
public interface IMementoNarrow
{
}
public interface IMementoWide
{
public void SetState(State state);
public State GetState();
}
public class Memento : IMementoNarrow, IMementoWide
{
private State state;
public Memento()
{
}
public void SetState(State state)
{
this.state = state;
}
public State GetState()
{
return this.state;
}
}
public class State
{
public string someState;
}
Originator
public class Originator
{
public IMementoNarrow CreateMemento()
{
return new Memento();
}
public void SetMemento(IMementoNarrow memento)
{
var mementoWide = memento as IMementoWide;
}
public void Foo()
{
}
}
Caretaker
public class Caretaker
{
private Originator originator;
private IMementoNarrow prevMemento;
public void SomeExecuteFunction()
{
this.originator.Foo();
this.prevMemento = this.originator.CreateMemento();
}
public void SomeUndoFunction()
{
this.originator.SetMemento(this.prevMemento);
}
}
Observer
Subject
public abstract class Subject
{
protected List<Observer> observers = null;
public virtual void Attach(Observer observer)
{
this.observers.Add(observer);
}
public virtual void Detach(Observer observer)
{
this.observers.Remove(observer);
}
public virtual void Notify()
{
foreach (var observer in this.observers)
{
observer.Update(this);
}
}
}
public class ConcreteSubject : Subject
{
public void Foo()
{
Notify();
}
}
Observer
public abstract class Observer
{
public abstract void Update(Subject changedSubject);
}
public class ConcreteObserver : Observer
{
public override void Update(Subject changedSubject)
{
}
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
var subject = new ConcreteSubject();
subject.Foo();
}
}
State
Context
public class Context
{
private State currentState;
public ConcreteStateA stateA { get; private set; }
public ConcreteStateB stateB { get; private set; }
public Context()
{
this.stateA = new ConcreteStateA();
this.stateB = new ConcreteStateB();
this.currentState = stateA;
}
public void Request()
{
this.currentState.Handle(this);
}
public void ChangeState(State state)
{
this.currentState = state;
}
}
State
public abstract class State
{
public abstract void Handle(Context context);
public virtual void ChangeState(Context context, State state)
{
context.ChangeState(state);
}
}
public class ConcreteStateA : State
{
public override void Handle(Context context)
{
ChangeState(context, context.stateB);
}
}
public class ConcreteStateB : State
{
public override void Handle(Context context)
{
ChangeState(context, context.stateA);
}
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
var context = new Context();
context.Request();
}
}
Strategy
- アルゴリズムをカプセル化する
- 1対多の関係で柔軟
- クライアントがConcreteStrategyを知っている場合
Context
public class Context
{
private Strategy strategy;
public Context(Strategy strategy)
{
this.strategy = strategy;
}
public void ContextInterface()
{
this.strategy.AlgorithmInterface();
}
}
Strategy
public abstract class Strategy
{
public abstract void AlgorithmInterface();
}
public class ConcreteStrategyA : Strategy
{
public override void AlgorithmInterface()
{
}
}
public class ConcreteStrategyB : Strategy
{
public override void AlgorithmInterface()
{
}
}
public class ConcreteStrategyC : Strategy
{
public override void AlgorithmInterface()
{
}
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
{
var strategyA = new ConcreteStrategyA();
var context = new Context(strategyA);
context.ContextInterface();
}
{
var strategyB = new ConcreteStrategyA();
var context = new Context(strategyB);
context.ContextInterface();
}
{
var strategyC = new ConcreteStrategyA();
var context = new Context(strategyC);
context.ContextInterface();
}
}
}
Template Method
TemplateMethod
public abstract class AbstractClass
{
public void TemplateMethod()
{
PrimitiveOperation1();
PrimitiveOperation2();
}
protected abstract void PrimitiveOperation1();
protected abstract void PrimitiveOperation2();
}
public class ConcreteClass : AbstractClass
{
protected override void PrimitiveOperation1()
{
}
protected override void PrimitiveOperation2()
{
}
}
Visitor
- オペレーションをカプセル化する
- 多対多の関係で柔軟
Visitor
public abstract class Visitor
{
public abstract void VisitConcreteElementA(ConcreteElementA elementA);
public abstract void VisitConcreteElementB(ConcreteElementB elementB);
}
public class ConcreteVisitor1 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA elementA)
{
}
public override void VisitConcreteElementB(ConcreteElementB elementB)
{
}
}
public class ConcreteVisitor2 : Visitor
{
public override void VisitConcreteElementA(ConcreteElementA elementA)
{
}
public override void VisitConcreteElementB(ConcreteElementB elementB)
{
}
}
Element
public abstract class Element
{
public abstract void Accept(Visitor visitor);
}
public class ConcreteElementA : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementA(this);
}
}
public class ConcreteElementB : Element
{
public override void Accept(Visitor visitor)
{
visitor.VisitConcreteElementB(this);
}
}
Structure
public class ObjectStructure
{
public IEnumerable<Element> SomeStructure;
}
SomeApplication
public class SomeApplication
{
public void SomeFunction()
{
var structureA = new ObjectStructure
{
SomeStructure = new List<ConcreteElementA>().Cast<Element>()
};
var structureB = new ObjectStructure
{
SomeStructure = new List<ConcreteElementB>().Cast<Element>()
};
var visitor1 = new ConcreteVisitor1();
var visitor2 = new ConcreteVisitor2();
foreach (var element in structureA.SomeStructure)
{
element.Accept(visitor1);
}
foreach (var element in structureA.SomeStructure)
{
element.Accept(visitor2);
}
foreach (var element in structureB.SomeStructure)
{
element.Accept(visitor1);
}
foreach (var element in structureB.SomeStructure)
{
element.Accept(visitor2);
}
}
}