C Sharp/デザインパターン
デザインパターン
[編集]C#はデザインパターンを実装するための柔軟な言語です。デザインパターンは、ソフトウェア開発における一般的な問題に対する再利用可能な解決策です。C#はこれらのパターンを簡単に実装できるよう設計されており、以下にいくつかの例を挙げます。
Singleton(シングルトン)
[編集]シングルトンパターンは、アプリケーション内で1つのインスタンスしか存在しないようにするためのパターンです。C#での実装には、static
フィールドを持つクラスと、そのクラスのインスタンスを作成するプライベートなコンストラクタを使用します。
using System; public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton Instance { get { instance ??= new Singleton(); return instance; } } } public class Program { public static void Main(string[] args) { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; Console.WriteLine(s1 == s2); // True: 同一のインスタンスを取得しているか確認 } }
このコードは、シングルトン(Singleton)パターンの例です。シングルトンパターンは、特定のクラスがインスタンス化される際に、そのクラスのインスタンスが常に1つだけであることを保証するためのパターンです。
Singleton
クラスには、プライベートな静的フィールドinstance
が含まれており、プライベートなコンストラクターが定義されています。このようにすることで、クラスの外部から新しいインスタンスを作成することができません。
Instance
プロパティは、シングルトンのインスタンスを返すために使用されます。最初の呼び出し時にinstance
がnull
である場合、instance
に新しいSingleton
インスタンスが代入されます。以降の呼び出しでは、すでに存在するinstance
が返されます。
Main
メソッドでは、Singleton.Instance
を使用して2つのSingleton
インスタンスを取得し、それらが同じインスタンスであることを確認するために比較しています。シングルトンパターンでは、複数のインスタンスを取得した場合でも、すべての取得が同じインスタンスを指していることを保証します。そのため、この例ではs1
とs2
は同じインスタンスを参照するため、比較の結果はTrue
になります。
Factory Method(ファクトリーメソッド)
[編集]ファクトリーメソッドパターンは、インスタンスの生成をカプセル化するためのパターンです。C#では、ファクトリメソッド、抽象ファクトリ、単純ファクトリなどの構築手法が利用できます。
using System; public interface IProduct { string GetName(); } public class ConcreteProductA: IProduct { public string GetName() => "Product A"; } public class ConcreteProductB: IProduct { public string GetName() => "Product B"; } public class ProductFactory { public IProduct CreateProduct(string type) { return type switch { "A" => new ConcreteProductA(), "B" => new ConcreteProductB(), _ => throw new NotSupportedException() }; } } class Program { static void Main(string[] args) { ProductFactory factory = new ProductFactory(); IProduct productA = factory.CreateProduct("A"); Console.WriteLine(productA.GetName()); // Output: Product A IProduct productB = factory.CreateProduct("B"); Console.WriteLine(productB.GetName()); // Output: Product B } }
このコードは、ファクトリーパターン(Factory Pattern)の一般的な例です。IProduct
インターフェースを実装した複数の具象製品クラスを作成し、ProductFactory
クラスを使用してこれらの具象クラスのインスタンスを生成します。
IProduct
は製品の共通のインターフェースであり、ConcreteProductA
とConcreteProductB
はそれぞれIProduct
を実装しています。GetName()
メソッドはIProduct
インターフェースに定義されており、各具象クラスではそれぞれ異なる製品名を返します。
ProductFactory
クラスは、与えられたタイプに応じて適切な製品のインスタンスを生成するCreateProduct()
メソッドを提供しています。Main
メソッドでは、ProductFactory
を使用して"A"
および"B"
のタイプの製品を作成し、それぞれの製品の名前を出力しています。
この設計パターンは、新しいオブジェクトを生成する際にクライアントコードから具象クラスの詳細を隠すことができます。代わりに、クライアントはファクトリーメソッドを介して製品のインスタンスを作成し、特定の製品の詳細に依存することなく、インターフェースを通じてそれらの製品を使用できます。
Observer(オブザーバ)
[編集]オブザーバパターンは、オブジェクト間の一対多の依存関係を定義するためのパターンです。C#では、イベントとデリゲートを使用して簡単に実装できます。
using System; public class Subject { public event EventHandler StateChanged; private string state; public string State { get => state; set { state = value; OnStateChanged(); } } protected virtual void OnStateChanged() { StateChanged?.Invoke(this, EventArgs.Empty); } } public class Observer { public void Subscribe(Subject subject) { subject.StateChanged += HandleStateChanged; } private void HandleStateChanged(object sender, EventArgs e) { // Handle the state change } } class Program { static void Main(string[] args) { Subject subject = new Subject(); Observer observer = new Observer(); observer.Subscribe(subject); subject.State = "Updated State"; // This will trigger HandleStateChanged in the Observer } }
このコードは、Observerパターン(観察者パターン)の基本的な実装を示しています。Subject(観察対象)の状態変化を監視し、その変化に応じて何らかのアクションを実行するObserver(観察者)を実装しています。
Subject
クラスは、StateChanged
というイベントを持ち、そのイベントが発生した際にOnStateChanged()
メソッドを呼び出しています。Observer
クラスは、Subject
のStateChanged
イベントにSubscribe
メソッドで登録し、イベントが発生した時にHandleStateChanged
メソッドを実行します。
Main
メソッドでは、Subject
インスタンスを作成し、Observer
に登録しています。その後、Subject
のState
プロパティを変更することで、HandleStateChanged
が呼び出されることが期待されます。
これらは、C#で一般的に使用されるデザインパターンの一部です。C#の強力な言語機能を活用して、さまざまなデザインパターンを実装し、ソフトウェアの保守性、再利用性、拡張性を向上させることができます。