はかせのラボ

私の頭の中を書いていく雑記ブログです

プログラミング MVPパターン ~実装編~

あいさつ

どうも、はかせです。
今回はいよいよMVPパターン実装です。

実装

まずはModel、View、Presenterのスクリプトから見ていきます。
Model

public interface IModel<T>
{
    ReadOnlyReactiveProperty<T> ModelRP();
    void SetModel(T inValue);
}

public class TestModel : MonoBehaviour, IModel<int>
{
    private ReactiveProperty<int> mValue;

    private void Awake()
    {
        mValue = new ReactiveProperty<int>();
        mValue.Subscribe(x => print(x));
    }

    public ReadOnlyReactiveProperty<int> ModelRP()
    {
        return mValue.ToReadOnlyReactiveProperty();
    }

    public void SetModel(int inValue)
    {
        mValue.Value = inValue;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            mValue.Value++;
        }
    }
}

View

public interface IView<T>
{
    ReadOnlyReactiveProperty<T> ViewRP();
    void SetView(T inValue);
}

public class TestView : MonoBehaviour, IView<int>
{
    private ReactiveProperty<int> mValue;
    public Text mText;

    private void Awake()
    {
        mValue = new ReactiveProperty<int>();
        mValue.Subscribe(x => mText.text = x.ToString());
    }

    public ReadOnlyReactiveProperty<int> ViewRP()
    {
        return mValue.ToReadOnlyReactiveProperty();
    }

    public void SetView(int inValue)
    {
        mValue.Value = inValue;
    }

}

Presenter

public class TestPresenter : MonoBehaviour
{
    private void Start()
    {
        var model = gameObject.GetComponent<IModel<int>>();
        var view = gameObject.GetComponent<IView<int>>();
        model.ModelRP().Subscribe(x => view.SetView(x));
        view.ViewRP().Subscribe(x => model.SetModel(x));
    }
}

今回監視と通知にはUniRxのReactivePropertyを使用しています。
(UnityでやるときはUniRx使うのがいいと思います。何より実装が楽ですw)
(そして楽だから改めて説明することがないという致命的な問題がありますw)

ModelとViewは保持しているReactivePropertyの公開と
値の通知を受ける用のメソッドを用意しています。
またModelの実装にはとりあえずSpaceキー入力があった時、
保持している値をインクリメントするようにしてます。

本来のMVPではViewからも更新がModelに行きますが、
今回はざっくりとした説明目的なので
View側は更新を受けてUIの更新のみを行っています。

では実行結果です。
f:id:hakase0274:20190320234124g:plain

単純に数値が増えているだけですが
UIとロジックの分離には成功しています。

あとがき

今回はMVPパターン実装編でした。

今回の実装ではPresenterのみModelとViewを知っており、
ModelとViewは他の誰も知らないような実装にしました。
入力などにしてもModelやViewが受け取る形にして
とにかくUIと内部ロジックを完全に分断しています。

他にも入力はPresenterが受け取りそれぞれModelとViewに伝えるパターンや、
ModelやViewがPresenterに対して
通知を飛ばしてPresenterを動かすパターンなど
色々な設計や実装があります。

今回の実装はあくまで私がプライベートで使う時に
一番よく使うパターンをあげただけです。

実際使う時は、自分が参加しているプロジェクトにとって
最良のパターンを選択して実装するのがいいと思います。

それでは今回はこの辺でノシ