JavaにおけるModel-View-ViewModelパターン:よりクリーンなコードのためのUIとロジックの分離
別名
- MVVM
Model-View-ViewModelデザインパターンの目的
JavaにおけるModel-View-ViewModel (MVVM)パターンの目的は、UIロジック、プレゼンテーションロジック、ビジネスロジック間の明確な懸念事項の分離を提供することです。アプリケーションをModel、View、ViewModelの3つの相互接続されたコンポーネントに分割することで実現します。
現実世界の例を用いたModel-View-ViewModelパターンの詳細な説明
現実世界の例
料理番組を例に、MVVMパターンの現実世界の類似例を考えてみましょう。
Model:レシピそのものを表します。材料と料理に必要な手順が含まれます。モデルは料理の準備に関するデータとルールのみを扱っており、視聴者への情報の提示方法については考慮しません。
View:料理番組を撮影するキッチンセットに例えられます。キッチンのレイアウト、材料の配置、調理器具など、すべての視覚要素が含まれます。ビューは視覚的なプレゼンテーションと、視聴者が料理プロセスをどのように見るかを担当します。
ViewModel:料理番組の台本のようなものです。レシピ(モデル)を解釈し、番組の流れを整理します。シェフ(ビュー)に次に何を表示するか、いつ材料を追加するか、材料の代替などへの対応方法を指示します。ViewModelは、レシピの技術的な詳細とシェフのプレゼンテーションのギャップを埋めることで、視聴者がレシピ自体の複雑さに立ち入ることなく、各ステップを理解できるようにします。
この例では、ViewModelにより、シェフは料理と視聴者との交流に集中でき、基盤となるレシピは変更されません。これにより、懸念事項の明確な分離が促進されます。
簡単に言うと
MVVMデザインパターンは、アプリケーションを3つの異なるコンポーネントに分割します。データとビジネスロジックを保持するModel、ユーザーインターフェースを表示するView、そしてModelからViewにデータをバインドする仲介役として機能するViewModelです。
Wikipediaによると
Model–view–viewmodel (MVVM) は、グラフィカルユーザーインターフェース(ビュー)の開発(マークアップ言語またはGUIコードによる)とビジネスロジックまたはバックエンドロジック(モデル)の開発を分離するソフトウェアアーキテクチャパターンです。これにより、ビューは特定のモデルプラットフォームに依存しなくなります。
JavaにおけるModel-View-ViewModelパターンのプログラミング例
ViewModelはビジネスロジックを保持し、モデルからのデータをビューに公開します。
public class BookViewModel {
@WireVariable
private List<Book> bookList;
private Book selectedBook;
private BookService bookService = new BookServiceImpl();
public Book getSelectedBook() {
return selectedBook;
}
@NotifyChange("selectedBook")
public void setSelectedBook(Book selectedBook) {
this.selectedBook = selectedBook;
}
public List<Book> getBookList() {
return bookService.load();
}
/** Deleting a book.
*/
@Command
@NotifyChange({"selectedBook","bookList"})
public void deleteBook() {
if (selectedBook != null) {
getBookList().remove(selectedBook);
selectedBook = null;
}
}
ビューにはロジックがなく、UI要素のみです。
<zk>
<window title="List of Books" border="normal" width="600px" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('com.iluwatar.model.view.viewmodel.BookViewModel')">
<vbox hflex="true">
<listbox model="@bind(vm.bookList)" selectedItem="@bind(vm.selectedBook)" height="400px" mold="paging">
<listhead>
<listheader label="Book Name"/>
<listheader label="Author"/>
</listhead>
<template name="model" var="book">
<listitem >
<listcell label="@bind(book.name)"/>
<listcell label="@bind(book.author)"/>
</listitem>
</template>
</listbox>
</vbox>
<toolbar>
<button label="Delete" onClick="@command('deleteBook')" disabled="@load(empty vm.selectedBook)" />
</toolbar>
<hbox style="margin-top:20px" visible="@bind(not empty vm.selectedBook)">
<vbox>
<hlayout>
Book Name : <label value="@bind(vm.selectedBook.name)" style="font-weight:bold"/>
</hlayout>
<hlayout>
Book Author : <label value="@bind(vm.selectedBook.author)" style="font-weight:bold"/>
</hlayout>
<hlayout>
Book Description : <label value="@bind(vm.selectedBook.description)" style="font-weight:bold"/>
</hlayout>
</vbox>
</hbox>
</window>
</zk>
例を実行するには、model-view-viewmodelフォルダに移動して実行します。
mvn clean install
mvn jetty:run -Djetty.http.port=9911
- ブラウザで次のアドレスを開きます:http://localhost:9911/model-view-viewmodel/
JavaでModel-View-ViewModelパターンを使用するケース
MVVMは、ユーザーインターフェースと基盤となるビジネスロジックの明確な分離が必要なアプリケーション、特にUIとビジネスロジックが独立して変化する大規模なデータ駆動型アプリケーションに適用できます。このため、Model-View-ViewModelパターンはJavaアプリケーションに最適です。
Model-View-ViewModelパターンのJavaチュートリアル
- Androidにおけるデータバインディング (developer.android.com)
- Model View View Model (MVVM)入門 (GeeksforGeeks)
- パターン - Model-View-ViewModelデザインパターンを使用したWPFアプリ (Microsoft)
JavaにおけるModel-View-ViewModelパターンの現実世界のアプリケーション
- デスクトップインターフェースのJavaFXアプリケーションで広く使用されています。
- 反応型のUI更新のために、DataBindingやLiveDataなどのライブラリを使用してAndroid開発で使用されています。
- ZKフレームワーク zkoss.org
- KnockoutJS knockoutjs.com
Model-View-ViewModelパターンのメリットとデメリット
メリット
- ビジネスロジックとプレゼンテーションロジックのデカップリングによるテスト容易性の向上。
- 基盤となるデータモデルに影響を与えることなく、ユーザーインターフェースの保守と変更が容易になります。
- 汎用的に設計された場合、異なるビュー間でViewModelの再利用性が向上します。
デメリット
- より単純なパターンで十分な小規模アプリケーションでは、複雑さが増します。
- パターンを正しく理解し適用するための学習曲線。
関連するJavaデザインパターン
- MVC (Model-View-Controller):MVVMは、MVCの派生と見なすことができ、バインディングとデカップリングに重点が置かれています。ViewModelはMVCのコントローラーとは異なり、仲介役として機能します。
- MVP (Model-View-Presenter):MVVMに似ていますが、プレゼンターがUIロジックを処理することに重点が置かれています。そのため、MVVMのViewModelは、直接的なUI操作という点ではより受動的です。