LoginSignup
9
5

More than 5 years have passed since last update.

UnityのScript構成を考えてみる その2

Last updated at Posted at 2016-12-28

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

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5