Java 中的 Model-View-Intent 模式:使用 MVI 构建健壮且可扩展的 Java UI
也称为
- MVI
Model-View-Intent 设计模式的意图
Java 应用程序的 Model-View-Intent (MVI) 模式在 Model、View 和 Intent 组件之间创建了一个单向循环数据流,从而增强了 UI 的可预测性和状态管理。
Model-View-Intent 模式的详细说明,并附带现实世界示例
现实世界示例
使用快餐店点餐场景,考虑 Java 中 Model-View-Intent (MVI) 模式的现实世界类比,以了解它在增强 UI 状态管理中的应用。
在这个类比中
- 模型:就像餐厅的厨房,管理您订单的当前状态。当您选择商品时,厨房会更新订单状态和使用的食材。
- 视图:代表菜单和数字显示屏,您可以在上面看到您当前的订单摘要。它反映您订单的当前状态,显示您添加或删除的商品。
- 意图:将其视为您与菜单交互时的决策过程。您做出的每个选择(例如添加汉堡或删除饮料)都会向系统(厨房)发送特定意图。
当您决定将商品添加到订单中(意图)时,厨房(模型)会处理此请求,更新您的订单状态,然后显示屏(视图)更新以显示您订单的最新状态。此循环会一直持续到您最终确定订单,这展示了 MVI 的单向循环流特征。这确保订单中的每一次变化都会在客户的视图中得到可预测且准确地反映,类似于软件中使用 MVI 时,UI 组件如何响应状态变化而更新。
通俗地说
Model-View-Intent (MVI) 模式是一种响应式架构方法,用户操作(意图)会修改应用程序状态(模型),然后更新后的状态会在用户界面(视图)中以单向循环数据流的方式反映出来。
Java 中 Model-View-Intent 模式的编程示例
Java 的 Model-View-Intent (MVI) 模式是一种构建应用程序逻辑的现代方法,它可以确保数据和事件的流畅单向流动。它是 Model-View-Presenter (MVP) 和 Model-View-ViewModel (MVVM) 模式的变体,但数据和事件的流动更加简化。
在 MVI 中,视图将用户事件发送到意图。意图将这些事件转换为模型中的状态变化。然后,模型将这种新状态推送到视图,视图相应地更新自身。这创建了一个单向数据流,它可以使您的代码更易于理解和调试。
首先,我们有 App
类,它充当应用程序的入口点。它创建视图和视图模型,然后模拟用户与计算器的一系列交互。
public final class App {
private static final double RANDOM_VARIABLE = 10.0;
public static void main(final String[] args) {
var view = new CalculatorView(new CalculatorViewModel());
var variable1 = RANDOM_VARIABLE;
view.setVariable(variable1);
view.add();
view.displayTotal();
variable1 = 2.0;
view.setVariable(variable1);
view.subtract();
view.divide();
view.multiply();
view.displayTotal();
}
private App() {
}
}
CalculatorView
类代表 MVI 中的视图。它接收用户事件(在本例中由 App
类模拟),并将其发送到视图模型。当它从视图模型接收到新状态时,它也会更新其显示。
public class CalculatorView {
private CalculatorViewModel viewModel;
public CalculatorView(CalculatorViewModel viewModel) {
this.viewModel = viewModel;
}
public void setVariable(double variable) {
viewModel.process(new SetVariableEvent(variable));
}
public void add() {
viewModel.process(new AddEvent());
}
public void subtract() {
viewModel.process(new SubtractEvent());
}
public void divide() {
viewModel.process(new DivideEvent());
}
public void multiply() {
viewModel.process(new MultiplyEvent());
}
public void displayTotal() {
System.out.println("Total: " + viewModel.getState().getTotal());
}
}
CalculatorViewModel
类代表 MVI 中的视图模型。它接收来自视图的事件,相应地更新模型的状态,然后将新状态推送到视图。
public class CalculatorViewModel {
private CalculatorModel model;
public CalculatorViewModel() {
this.model = new CalculatorModel();
}
public void process(UserEvent event) {
event.apply(model);
}
public CalculatorModel getState() {
return model;
}
}
CalculatorModel
类代表 MVI 中的模型。它保存计算器的当前状态,并提供用于更新该状态的方法。
public class CalculatorModel {
private double total;
private double variable;
public void setVariable(double variable) {
this.variable = variable;
}
public void add() {
total += variable;
}
public void subtract() {
total -= variable;
}
public void divide() {
total /= variable;
}
public void multiply() {
total *= variable;
}
public double getTotal() {
return total;
}
}
最后,UserEvent
接口及其实现代表可能发生的各种用户事件。每个事件都知道如何将自身应用到模型中。
public interface UserEvent {
void apply(CalculatorModel model);
}
public class SetVariableEvent implements UserEvent {
private double variable;
public SetVariableEvent(double variable) {
this.variable = variable;
}
@Override
public void apply(CalculatorModel model) {
model.setVariable(variable);
}
}
// Similar classes would be created for AddEvent, SubtractEvent, DivideEvent, and MultiplyEvent ...
此示例演示了 MVI 模式的关键方面:单向数据流、明确的关注点分离以及使用事件驱动模型状态的变化。
何时在 Java 中使用 Model-View-Intent 模式
- MVI 模式在具有复杂用户界面、需要明确的关注点分离、可预测的状态管理以及增强可维护性的 Java 应用程序中非常有用。
- 通常应用于响应式编程环境,以确保流畅的数据流和状态一致性。
Model-View-Intent 模式 Java 教程
Java 中 Model-View-Intent 模式的实际应用
- 广泛应用于响应式和事件驱动的 Java 应用程序,尤其是那些使用 RxJava 或 Project Reactor 等框架的应用程序。
- 用于 Android 开发,尤其是在使用 RxJava 和 LiveData 等支持响应式编程的库时。
Model-View-Intent 模式的优缺点
优点
- 通过建立清晰的循环数据流,增强了 UI 的可预测性。
- 由于组件之间有明确的分离,因此提高了可测试性。
- 通过在模型中集中状态,支持更好的状态管理。
权衡
- 由于结构化和循环流,对于简单的 UI 来说,复杂度会增加。
- 需要熟悉响应式编程范式。
- 如果没有正确管理,可能会导致样板代码。
相关的 Java 设计模式
Model-View-ViewModel (MVVM):与分离视图和模型的目标类似,但不同之处在于 MVI 引入了循环数据流。
Model-View-Controller (MVC):可以将 MVI 看作是 MVC 的演变,它更加注重响应式编程和单向数据流。
观察者:在 MVI 中至关重要,用于观察模型中的变化并相应地更新视图。