
C#初心者を卒業しよう(第2回)Factory Method
はじめに
今回は前回の Static Factory のサンプルを Factory Method に書き換えます。
Factory Method は GoF(Gang of Four) のパターンで、インスタンスを生成する場所を一箇所にまとめます。
早速始めましょう
前回作成した Static Factory を DistanceFactory クラスに押し込んでしまうイメージです。
ToYards クラス、ToMeters クラスは変更ありません。
var service = new DistanceService();
service.Run();
public interface IDistance
{
void Calculate(double distance);
string CreateAnswerMessage();
}
public class DistanceService
{
public void Run()
{
var convertNumber = InputConvertNumber();
var distanceObject = Create(convertNumber);
var distance = InputDistance();
distanceObject.Calculate(distance);
OutputAnswer(distanceObject);
}
protected virtual int InputConvertNumber()
{
Console.WriteLine("Please input convert number.");
Console.WriteLine("1 : Convert meters to yards.");
Console.WriteLine("2 : Convert yards to meters.");
if (!int.TryParse(Console.ReadLine(), out var convertNumber))
{
throw new FormatException("Invalid input convert number.");
}
return convertNumber;
}
protected virtual IDistance Create(int convertNumber)
{
switch (convertNumber)
{
case 1:
return new ToYards();
case 2:
return new ToMeters();
default:
throw new ArgumentOutOfRangeException(
$"{convertNumber} is out of range.");
}
}
protected virtual double InputDistance()
{
Console.WriteLine("Please input distance.");
if (!double.TryParse(Console.ReadLine(), out var distance))
{
throw new FormatException("Invalid input distance.");
}
return distance;
}
protected virtual void OutputAnswer(IDistance distance)
{
var outputMessage = distance.CreateAnswerMessage();
Console.WriteLine(outputMessage);
}
}
public class ToMeters : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double yards)
{
_yards = yards;
_meters = yards / 1.0936133d;
}
public string CreateAnswerMessage()
{
return $"{_yards} yards is {_meters} meters.";
}
}
public class ToYards : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_yards = meters * 1.0936133d;
}
public string CreateAnswerMessage()
{
return $"{_meters} meters is {_yards} yards.";
}
}
ダウンロード
ダウンロード用に置いてあるものは、クラスごとにファイルを分けてあります。
練習問題
より理解を深めるために、以下の練習問題に取り組んでみてください。
練習問題 02
今回の練習問題は、前回と全く同じです。
このサンプルプログラムに
「メートル」を「フィート」に、
「フィート」を「メートル」に
変換できる機能を追加してください。
機能を追加したら、前回の練習問題で作成したプログラムと比較してみてください。
おわりに
次回は、このサンプルを DI コンテナを使うように書き直します。Dependency Injection と言った方が分かりやすいかも知れません。お楽しみに。
いいなと思ったら応援しよう!
