http://qiita.com/nakatatsu/items/7af160372a31e95cf8fd の続き。
前回の反省と今回の改善
さて前回、ロジックやらInputFieldの操作やらが全部入っていたGodViewクラスを分離して下記のようなメソッドが含まれるクラス"View"と"Logic"クラスに書き直した。
つまりは表示とロジックを分離したのだが、
View.cs
// logic
var output = logic.Pow(Int32.Parse(input));
このとおりViewにlogicと書いてあるくらいで、まだまだ普通にロジックを持ってしまっている。
最終的にViewはLogicを監視するのみにしたい。
3. Observerパターン導入によるLogicとViewの疎結合化
というわけでさらに修正してみたのがこちら。
View.cs
using System;
using UnityEngine;
using UnityEngine.UI;
public class View : MonoBehaviour
{
private InputField InputForm;
private Text OutputText;
private Logic logic;
private void Start()
{
logic = new Logic();
InputForm = GameObject.Find("InputForm").GetComponent<InputField>();
OutputText = GameObject.Find("OutputText").GetComponent<Text>();
logic.Calculated += new Logic.NumberChangedEventHandler((int sender) => OutputText.text = "処理結果 " + sender.ToString());
}
private bool Check(string input)
{
bool valid = true;
int tmp;
if (!Int32.TryParse(input, out tmp))
{
OutputText.text = "整数のみ入力可";
valid = false;
}
return valid;
}
public void OnClickPow()
{
// check
if (!Check(InputForm.text))
return;
// logic
logic.Pow(Int32.Parse(InputForm.text));
}
public void OnClickIncrement()
{
// check
if (!Check(InputForm.text))
return;
// logic
logic.Increment(Int32.Parse(InputForm.text));
}
public void OnClickDecrement()
{
// check
if (!Check(InputForm.text))
return;
// logic
logic.Decrement(Int32.Parse(InputForm.text));
}
}
Logic.cs
using System;
using System.IO;
public class Logic
{
public delegate void NumberChangedEventHandler(int sender);
public event NumberChangedEventHandler Calculated;
public void Pow(int number)
{
int result = (int) Math.Pow(number, 2);
Save(Config.PersistentDataPath + "/pow.txt", result.ToString());
Calculated(result);
}
public void Increment(int number)
{
int result = number + 1;
Save(Config.PersistentDataPath + "/increment.txt", result.ToString());
Calculated(result);
}
public void Decrement(int number)
{
int result = number - 1;
Save(Config.PersistentDataPath + "/decrement.txt", result.ToString());
Calculated(result);
}
private void Save(string filePath, string contents)
{
using (var fileStream = new FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
{
using (var writer = new StreamWriter(fileStream))
{
writer.Write(contents);
}
}
}
}
- Observerパターンを導入した結果、LogicクラスがViewクラスのために値を返さなくてもよくなった。
- チェック部分を関数ごとView側に戻して共通化。
- ※ ただし正直要改善。ほかの人はどうやっているのだろう……>値のチェック
- logicをフィールドで持つようにした。これは使いまわすことが目的ではなく、将来的にDIやFactoryの導入を検討してのこと。
決して完了とは言えないものの、Logic側の手直しに移ろうと思う。
参考
GUIアーキテクチャパターンの基礎からMVVMパターンへ
https://www.slideboom.com/presentations/591514/GUI%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3