Extenject (+ MV(R)P) に触れてみた
Extenject とは
Unity用のDIフレームワークという認識.
DIって何?
よく言われているDependency Injection.
DIの説明としては,以下の記事に詳しく書かれている.
【Unity】Zenjectに学ぶDependency Injection - Qiita
詳細を外部から渡すことで疎結合にしていくアプローチがDI. しかし,いくら抽象化して疎結合して行っても,最終的には必ず誰かが依存関係を知ることになる. DIパターンを実装する場合,依存関係を知っている専門のクラスを用意して,そのクラスがインスタンスを渡すという アプローチを取る.この役割をDIコンテナと呼ぶ.
Extenjectの機能・特徴
Extenject(旧Zenject)はDIを行うための機能を持つだけでなく,下記の機能も持つ.
- MonoBehaviourを継承せずにUpdateを行う機能
- Pub/Sub
- Object Pool
また,特定のソフトウェアアーキテクチャに依存しない特徴を持つ. MVC,MV(R)P,MVVM,Clean Architectureなどなど.
Extenjectを軽く触れてみる
こちらの記事のサンプルを利用しました.
https://matcha-choco010.net/2019/08/24/unity-mvrp-zenject-multiscene/
Extenject触れる前はコメントアウトしている.
MVPの作り方は下記記事詳細.
(はじめてのUniRx from torisoupさんより抜粋)
Model
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; public class TestHPModel //: MonoBehaviour { private ReactiveProperty<int> _hp = new ReactiveProperty<int>(100); public IReadOnlyReactiveProperty<int> HP => _hp; public void Damage(int damage) { var tmp = _hp.Value - damage; _hp.Value = (tmp < 0) ? 0 : tmp; } }
ModelはMonoBehaviourを継承する必要がなくなり,適当な空GameObjectにアタッチしなくてもよくなった.
View
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; using TMPro; using UniRx; using UnityEngine.UI; public class TestHPView : MonoBehaviour { [SerializeField] private TextMeshProUGUI text; [SerializeField] private Button button; public IObservable<Unit> OnDamage => button.OnClickAsObservable(); public void DisplayHP(int hp) { text.text = hp.ToString(); } }
Viewは変わらず.
Presenter
using System.Collections; using System.Collections.Generic; using UnityEngine; using UniRx; using Zenject; public class TestPresenter //: MonoBehaviour { // //Extenject導入前 // public TestHPView TestHPView; // public TestHPModel TestHPModel; // void Start() // { // // Model -> View // TestHPModel.HP.Subscribe(TestHPView.DisplayHP); // // View -> Model // TestHPView.OnDamage.Subscribe(_ => TestHPModel.Damage(20)); // } // Extenject導入後 public TestPresenter(TestHPView testHPView, TestHPModel testHPModel) { // Model -> View testHPModel.HP.Subscribe(testHPView.DisplayHP); // View -> Model testHPView.OnDamage.Subscribe(_ => testHPModel.Damage(20)); } }
Presenterは劇的に変わった.素晴らしい.
MonoBehaviourの継承がなくなってアタッチする必要なくなったし,
ViewとModelをインスペクタで逐一D&Dとかする必要がなくなった.
StartではなくコンストラクタでViewとModelを受け取り(典型的なDIパターン),処理をしている.
終わりに
こちらの「ZenjectチョットワカルBook」の2章まで読んだ.
ZenjectチョットワカルBook - EFB~相手は死ぬ~ - BOOTH
DI自体の概念は業務でバリバリSpringフレームワークみたいなので触れたり, Factoryを作ってたりしていたので,すぐに理解できた.
Factory Methodパターン参照.
後はExtenject特有のBindの記述式とかやり方とかに慣れていこうと思います.
上のZenjectチョットワカルBookは上巻らしい. 下巻出るまでに完全に理解したい.
設計系とかUniRxとか楽しいけど沼を感じる. ちゃんと理解できるところまでどこまでいけるだろうか….ガンバロウ.