背景
Abstractパターンの理解を深めるため、「抽象クラスを使用するAbstractパターン」と「インターフェースを使用するAbstractパターン」を参考にして、それぞれのコードをキングダムバージョンに置き換えてみました。置き換えに際しては、本能型の武将と知略型の武将が蛇甘平原と黒羊丘で戦うモデルを取り上げています。
【蛇甘(だかん)平原】 : 本能型の武将(麃公)と知略型の武将(呉慶)が激突します。
【黒羊丘】 : 本能型の武将(信)と知略型の武将(慶舎)が激突します。
Abstractパターンとは
● 組み合わせて使う多数のサブクラス群を、まとめて交換できるようにするパターンです。
【GoFのデザインパターン】「Abstract Factory」ってどんなパターン?
● 関連のある一連のオブジェクト郡をまとめて生成する方法を提供するパターンです。
Abstract Factory パターン
● インスタンスの生成を専門に行うクラスを用意することで、整合性を必要とされる一連のオブジェクト群を間違いなく生成するためのパターンです。
8. AbstractFactory パターン
テスト環境
Microsoft Visual Studio Community 2019 ( Version 16.11.0 )
①抽象クラスを使用するパターン
AbstractPattern1.cs
using System;
namespace AbstractFactoryEx
{
public class AbstractFactoryEx
{
public static void Main()
{
// Create and run the DakanPlainsSituation
PlaceFactory dakanPlains = new DakanPlainsFactory();
TheWarringStatesPeriod period1 = new TheWarringStatesPeriod(dakanPlains);
Console.WriteLine("DakanPlains");
period1.runBattle();
// Create and run the KokuyoHillsSituation
PlaceFactory kokuyoHills = new KokuyoHillsFactory();
TheWarringStatesPeriod period2 = new TheWarringStatesPeriod(kokuyoHills);
Console.WriteLine("KokuyoHills");
period2.runBattle();
Console.ReadKey(true);
}
}
/// <summary>
/// The 'AbstractFactory' abstract class
/// </summary>
abstract class PlaceFactory
{
public abstract InstinctType createInstinctType();
public abstract IntellectualType createIntellectualType();
}
/// <summary>
/// The 'ConcreteFactory1' class
/// </summary>
///
class DakanPlainsFactory : PlaceFactory
{
public override InstinctType createInstinctType()
{
return new Hyoko();
}
public override IntellectualType createIntellectualType()
{
return new Gokei();
}
}
/// <summary>
/// The 'ConcreteFactory2' class
/// </summary>
class KokuyoHillsFactory : PlaceFactory
{
public override InstinctType createInstinctType()
{
return new Shin();
}
public override IntellectualType createIntellectualType()
{
return new Keisya();
}
}
/// <summary>
/// The 'AbstractProductA' abstract class
/// </summary>
abstract class InstinctType
{
//public abstract void sense(IntellectualType Intelect);
public abstract void sense(IntellectualType Intelect);
}
/// <summary>
/// The 'AbstractProductB' abstract class
/// </summary>
abstract class IntellectualType
{
public abstract void predict(InstinctType Instinct);
}
/// <summary>
/// The 'ProductA1' class
/// </summary>
class Hyoko : InstinctType
{
//public abstract void sense(IntellectualType Intelect);
public override void sense(IntellectualType Intelect)
{
Console.WriteLine(this.GetType().Name + " sense " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'ProductB1' class
/// </summary>
class Gokei : IntellectualType
{
public override void predict(InstinctType Instinct)
{
Console.WriteLine(this.GetType().Name + " predict " + Instinct.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'ProductA2' class
/// </summary>
class Shin : InstinctType
{
//public override void sense(IntellectualType Intelect)
public override void sense(IntellectualType Intelect)
{
Console.WriteLine(this.GetType().Name + " sense " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'ProductB2' class
/// </summary>
class Keisya : IntellectualType
{
public override void predict(InstinctType Instinct)
{
Console.WriteLine(this.GetType().Name + " predict " + Instinct.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'Client' class
/// </summary>
class TheWarringStatesPeriod
{
private InstinctType _instinctType;
private IntellectualType _intellectualType;
public TheWarringStatesPeriod(PlaceFactory factory)
{
_instinctType = factory.createInstinctType();
_intellectualType = factory.createIntellectualType();
}
public void runBattle()
{
_instinctType.sense(_intellectualType);
_intellectualType.predict(_instinctType);
}
}
}
出力結果
DakanPlains
Hyoko sense Gokei's behavior.
Gokei predict Hyoko's behavior.
DakanPlains
Shin sense Keisya's behavior.
Keisya predict Shin's behavior.
次に、インターフェースを使用したバージョンを見てみます。
何らかの拍子で、信が知略型の素質を開花させたとします。
②インターフェースを使用するパターン
AbstractPatternTest.cs
using System;
namespace AbstractPatternEx
{
class Program
{
static void Main(string[] args)
{
new TheWarringStatesPeriod().initializePeriod();
Console.ReadKey(true);
}
}
/// <summary>
/// The 'AbstractFactory' abstract class
/// </summary>
public interface IPlaceFactory
{
I_InstinctType CreateInstinctType();
I_IntellectualType CreateIntellectualType();
}
/// <summary>
/// The 'ConcreteFactory1' class
/// </summary>
class DakanPlainsFactory : IPlaceFactory
{
public I_InstinctType CreateInstinctType()
{
return new Hyoko();
}
public I_IntellectualType CreateIntellectualType()
{
return new Gokei();
}
}
/// <summary>
/// The 'ConcreteFactory2' class
/// </summary>
class KokuyoHillsFactory : IPlaceFactory
{
public I_InstinctType CreateInstinctType()
{
return new Shin();
}
public I_IntellectualType CreateIntellectualType()
{
return new Keisya();
}
}
/// <summary>
/// The 'AbstractProductA' abstract class
/// </summary>
public interface I_InstinctType
{
void sense(I_IntellectualType Instinct);
/// <summary>
/// 可能性としてのpredict関数。
/// この能力が使えるかは、各人の素質にかかっている。
/// </summary>
/// <param name="Instinct"></param>
void predict(I_IntellectualType Instinct);
}
/// <summary>
/// The 'ProductA1' class
/// </summary>
class Hyoko : I_InstinctType
{
public void sense(I_IntellectualType Intelect)
{
Console.WriteLine(this.GetType().Name + " sense " + Intelect.GetType().Name + "'s behavior.");
}
public void predict(I_IntellectualType Intelect)
{
//Hyokoは、知略型の素質を発現できなかった。
//Console.WriteLine(this.GetType().Name + " sense " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'ProductA2' class
/// </summary>
class Shin : I_InstinctType
{
public void sense(I_IntellectualType Intelect)
{
Console.WriteLine(this.GetType().Name + " sense " + Intelect.GetType().Name + "'s behavior.");
}
public void predict(I_IntellectualType Intelect)
{
//Shinは、知略型の素質を発現できた。
Console.WriteLine(this.GetType().Name + " predict " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'AbstractProductB' abstract class
/// </summary>
public interface I_IntellectualType
{
void predict(I_InstinctType Instinct);
}
/// <summary>
/// The 'ProductB1' class
/// </summary>
class Gokei : I_IntellectualType
{
public void predict(I_InstinctType Intelect)
{
Console.WriteLine(this.GetType().Name + " predict " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'ProductB2' class
/// </summary>
class Keisya : I_IntellectualType
{
public void predict(I_InstinctType Intelect)
{
Console.WriteLine(this.GetType().Name + " predict " + Intelect.GetType().Name + "'s behavior.");
}
}
/// <summary>
/// The 'Client' class
/// 春秋戦国時代クラス
/// </summary>
class TheWarringStatesPeriod
{
public void initializePeriod()
{
Console.WriteLine("DakanPlains");
runBattle(new DakanPlainsFactory());
Console.WriteLine("DakanPlains");
runBattle(new KokuyoHillsFactory());
}
public void runBattle(IPlaceFactory factory)
{
var InstinctType = factory.CreateInstinctType();
var IntellectualType = factory.CreateIntellectualType();
InstinctType.sense(IntellectualType);
InstinctType.predict(IntellectualType);
IntellectualType.predict(InstinctType);
}
}
}
出力結果
DakanPlains
Hyoko sense Gokei's behavior.
Gokei predict Hyoko's behavior.
DakanPlains
Shin sense Keisya's behavior.
Shin predict Keisya's behavior.
Keisya predict Shin's behavior.
参考資料
オブジェクト指向における再利用のためのデザインパターン(改訂版)
インターフェースとは?~継承とは役割が違う~|オブジェクト指向プログラミング(OOP)をおさらいしよう(3)
C# Abstract Factory
Abstract Factory in C#
↧