#色々あって間が空きましたが、ようやくこのシリーズを再開します。
さて、前回はFactoryの基本ということで、Simple Factoryを取り上げました。今回はFactory Methodパターンを取り上げます。
Factory Methodパターンはインスタンス化するクラスをサブクラスに決定させるため、インスタンス化をサブクラスに先送りできます。これにより、実際にオブジェクトを使用するクラスから具象クラスへの依存がなくなります。
といってもよくわからないので、コードを書いてみましょう。
- まず、生成されるオブジェクトのインタフェイスとなる抽象クラスAbstractMemberを定義します。ここで、インタフェイスとは広義の意味であり、interface(VBならInterface)で定義するインタフェイスのことではありません。
public abstract class AbstractMember
{
protected string name;
public abstract void Speak();
}
Public MustInherit Class AbstractMember
Protected name As String
Public MustOverride Sub Speak()
End Class
- AbstractMemberを継承した具象クラスMasaru, Epistemeを定義します。
public class Masaru : AbstractMember
{
public Masaru()
{
this.name = "まさる";
}
public override void Speak()
{
Console.WriteLine("名前は{0}です。", this.name);
Console.WriteLine("越後のとあるSIerで働いています。");
}
}
public class Episteme : AbstractMember
{
public Episteme()
{
this.name = "επιστημη";
}
public override void Speak()
{
Console.WriteLine("名前は{0}です。", this.name);
Console.WriteLine("わんくま茶藝部顧問です。");
}
}
Public Class Masaru
Inherits AbstractMember
Sub New()
Me.name = "まさる"
End Sub
Public Overrides Sub Speak()
Console.WriteLine("名前は{0}です。", Me.name)
Console.WriteLine("越後のとあるSIerで働いています。")
End Sub
End Class
Public Class Episteme
Inherits AbstractMember
Sub New()
Me.name = "επιστημη"
End Sub
Public Overrides Sub Speak()
Console.WriteLine("名前は{0}です。", Me.name)
Console.WriteLine("わんくま茶藝部顧問です。")
End Sub
End Class
- AbstractMemberを生成するための抽象クラスAbstractCreatorを定義します。
public abstract class AbstractCreator
{
public abstract AbstractMember CreateMember();
}
Public MustInherit Class AbstractCreator
Public MustOverride Function CreateMember() As AbstractMember
End Class
- AbstractCreatorを継承したインスタン生成のための具象クラスNormalMemberCreator、SuperMemberCreatorを定義します。
public class NormalMemberCreator : AbstractCreator
{
public override AbstractMember CreateMember()
{
return new Masaru();
}
}
public class SuperMemberCreator : AbstractCreator
{
public override AbstractMember CreateMember()
{
return new Episteme();
}
}
Public Class NormalMemberCreator
Inherits AbstractCreator
Public Overrides Function CreateMember() As AbstractMember
Return New Masaru()
End Function
End Class
Public Class SuperMemberCreator
Inherits AbstractCreator
Public Overrides Function CreateMember() As AbstractMember
Return New Episteme()
End Function
End Class
以上のコードを実行してみましょう。
実行コード
public static class Program
{
public static void Main(string[] args)
{
{
NormalMemberCreator memberCreator = new NormalMemberCreator();
AbstractMember member = memberCreator.CreateMember();
member.Speak();
}
Console.WriteLine("");
{
SuperMemberCreator memberCreator = new SuperMemberCreator();
AbstractMember member = memberCreator.CreateMember();
member.Speak();
}
Console.Read();
}
}
Public Class Program
Private Shared Block As Object = Nothing
Public Shared Sub Main(ByVal args As String())
With Block
Dim memberCreator As New NormalMemberCreator()
Dim member As AbstractMember = memberCreator.CreateMember()
member.Speak()
End With
Console.WriteLine("")
With Block
Dim memberCreator As New SuperMemberCreator()
Dim member As AbstractMember = memberCreator.CreateMember()
member.Speak()
End With
Console.ReadLine()
End Sub
End Class
実行結果
名前はまさるです。
越後のとあるSIerで働いています。
名前はεπιστημηです。
わんくま茶藝部顧問です。
上記の実行コードはSpeakメソッドを実装している具象クラスのことを知りません。これが依存性をなくしたということです。
これによって何が良いのかというと、例えばMasaruクラスでなく、Torikobitoクラスに変更したい場合、実行コードに変更が必要ありません。あくまでTorikobitoクラスの追加と、NormalMemberCreatorの変更だけで済みます。
変更点
public class Torikobito : AbstractMember
{
public Torikobito()
{
this.name = "とりこびと";
}
public override void Speak()
{
Console.WriteLine("名前は{0}です。", this.name);
Console.WriteLine("Memo(Of T)管理人です。");
}
}
public class NormalMemberCreator : AbstractCreator
{
public override AbstractMember CreateMember()
{
return new Torikobito();
}
}
Public Class Torikobito
Inherits AbstractMember
Sub New()
Me.name = "とりこびと"
End Sub
Public Overrides Sub Speak()
Console.WriteLine("名前は{0}です。", Me.name)
Console.WriteLine("Memo(Of T)管理人です。")
End Sub
End Class
Public Class NormalMemberCreator
Inherits AbstractCreator
Public Overrides Function CreateMember() As AbstractMember
Return New Torikobito()
End Function
End Class
実行結果
名前はとりこびとです。
Memo(Of T)管理人です。
名前はεπιστημηです。
わんくま茶藝部顧問です。
ということで、今回はFactory Methodパターンをお送りしましたが、私自身まだこのパターンの有用性が理解し切れていません。実際に「こんなときに使ったよ」などありましたらコメントで教えてください。