C#デザインパターン - FactoryMethod
ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 /
結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。
解説らしい解説は載せていませんので、『増補改訂版Java言語で学ぶデザインパターン入門
/ 結城 浩(著)』も合わせてお読みください。
※当ソースは、Visual C# 2008 Express Editionで動作を確認しています。
Visual Studio 2005をお使いの方は、ブログの記事を残しておきますので、そちらをご覧ください。
■IProduct.cs
using System; namespace Gushwell.DesignPatterns.Framework { public interface IProduct { void Use(); // IProductのメンバーに変更(結城氏の意図とは異なる可能性があるが...) string Owner { get; } } }
■Factory.cs
using System; using System.Collections.Generic; namespace Gushwell.DesignPatterns.Framework { public class Factory<T> where T : class, IProduct { private List<string> owners = new List<string>(); // T型のインスタンスを生成する。 public T Create(string owner) { // IProductnの派生クラスにデフォルトコンストラクタを用意し、 // Ownerを書き込み可のプロパティにすれば、わざわざリフレクションを // 使わなくても、以下のコードで良い。 // T p = new T(); // p.Owner = owner; // ただ、そうするとOwnerが読み込み専用のプロパティでなくなってしまう。 Type t = typeof(T); var obj = Activator.CreateInstance(t, owner); T p = obj as T; RegisterProduct(p); return p; } private void RegisterProduct(T product) { owners.Add(product.Owner); } // Owners は、IEnumerableを返すように変更 public IEnumerable<string> Owners { get { return owners; } } } }
■IDCard.cs
using System; using Gushwell.DesignPatterns.Framework; namespace Gushwell.DesignPatterns.Concrete { public class IDCard : IProduct { private string owner; public IDCard(string owner) { Console.WriteLine("{0} のカードを作ります。", owner); this.owner = owner; } public void Use() { Console.WriteLine("{0} のカードを使います。", owner); } public string Owner { get { return owner; } } } }
■Program.cs
using System; using Gushwell.DesignPatterns.Framework; using Gushwell.DesignPatterns.Concrete; using Gushwell.Dejavu; namespace Gushwell.DesignPatterns { public class Program { public static void Main(string[] args) { // Factoryクラスは、IProductを実装していれば、IDCard以外のインスタンスも生成できる var factory = new Factory<IDCard>(); // IDCardという具象クラスではなく、IProductというインターフェースに対して // プログラミングしている。 IProduct card1 = factory.Create("結城浩"); IProduct card2 = factory.Create("とむら"); IProduct card3 = factory.Create("佐藤花子"); card1.Use(); card2.Use(); card3.Use(); factory.Owners.ForEach(owner => Console.WriteLine(owner)); } } }
■EnumerableExtentions.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Gushwell.Dejavu { public static class EnumerableExtentions { public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) { foreach (var x in source) { action(x); } } public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> func) { int i = 0; foreach (var x in source) { func(x, i); i++; } } } }