MVP架构模式:餐厅点餐的有趣故事

故事背景:智能餐厅的点餐系统

想象一下,我们开了一家"代码美味"餐厅,餐厅里有三个角色:

  • 顾客 (View) :只会说"我要点餐"和看最终上来的菜品
  • 服务员 (Presenter) :负责接收订单、协调后厨、把菜品端给顾客
  • 厨师 (Model) :在后厨默默做饭,顾客看不到他

角色分工代码实现

1. 厨师 (Model) - 数据和处理逻辑

java 复制代码
// 厨师 - 负责真正的烹饪工作
public class Chef {
    public interface OnCookingListener {
        void onSuccess(String food);
        void onError(String message);
    }
    
    // 真正的业务逻辑在这里
    public void cookFood(String order, OnCookingListener listener) {
        new Thread(() -> {
            try {
                // 模拟烹饪时间
                Thread.sleep(2000);
                
                switch (order) {
                    case "宫保鸡丁":
                        listener.onSuccess("香喷喷的宫保鸡丁做好了!");
                        break;
                    case "麻婆豆腐":
                        listener.onSuccess("热辣辣的麻婆豆腐出锅了!");
                        break;
                    default:
                        listener.onError("抱歉,这道菜我们不会做");
                }
            } catch (InterruptedException e) {
                listener.onError("厨房出问题了!");
            }
        }).start();
    }
}

2. 服务员 (Presenter) - 业务协调员

java 复制代码
// 服务员 - 连接顾客和厨师的中介
public class Waiter {
    private CustomerView customerView;
    private Chef chef;
    
    public Waiter(CustomerView view) {
        this.customerView = view;
        this.chef = new Chef();
    }
    
    // 接收顾客订单,协调后厨工作
    public void takeOrder(String foodName) {
        // 先告诉顾客:订单已收到
        customerView.showLoading("正在为您准备 " + foodName + "...");
        
        // 然后把订单交给厨师
        chef.cookFood(foodName, new Chef.OnCookingListener() {
            @Override
            public void onSuccess(String result) {
                // 厨师做好了,服务员把菜品端给顾客
                customerView.hideLoading();
                customerView.showFood(result);
            }
            
            @Override
            public void onError(String message) {
                // 厨师说做不了,服务员告诉顾客
                customerView.hideLoading();
                customerView.showError(message);
            }
        });
    }
    
    // 清理工作
    public void onDestroy() {
        customerView = null;
    }
}

3. 顾客 (View) - 界面展示

java 复制代码
// 顾客接口 - 定义顾客能做什么
public interface CustomerView {
    void showLoading(String message);    // 显示等待
    void hideLoading();                  // 隐藏等待
    void showFood(String food);          // 展示菜品
    void showError(String message);      // 展示错误
}

// 具体的顾客 - Activity实现
public class RestaurantActivity extends AppCompatActivity implements CustomerView {
    private TextView statusText;
    private Button orderButton1, orderButton2;
    private ProgressBar progressBar;
    private Waiter waiter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_restaurant);
        
        // 初始化界面
        statusText = findViewById(R.id.status_text);
        orderButton1 = findViewById(R.id.btn_order1);
        orderButton2 = findViewById(R.id.btn_order2);
        progressBar = findViewById(R.id.progress_bar);
        
        // 请来服务员
        waiter = new Waiter(this);
        
        // 设置点餐按钮
        orderButton1.setOnClickListener(v -> waiter.takeOrder("宫保鸡丁"));
        orderButton2.setOnClickListener(v -> waiter.takeOrder("麻婆豆腐"));
    }
    
    // 实现顾客接口的方法
    @Override
    public void showLoading(String message) {
        runOnUiThread(() -> {
            progressBar.setVisibility(View.VISIBLE);
            statusText.setText(message);
        });
    }
    
    @Override
    public void hideLoading() {
        runOnUiThread(() -> {
            progressBar.setVisibility(View.GONE);
        });
    }
    
    @Override
    public void showFood(String food) {
        runOnUiThread(() -> {
            statusText.setText(food);
            Toast.makeText(this, "用餐愉快!", Toast.LENGTH_SHORT).show();
        });
    }
    
    @Override
    public void showError(String message) {
        runOnUiThread(() -> {
            statusText.setText(message);
            Toast.makeText(this, "出错了!", Toast.LENGTH_SHORT).show();
        });
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 餐厅打烊,服务员下班
        waiter.onDestroy();
    }
}

MVP调用时序图

错误情况的时序图

MVP的核心优势

1. 分工明确,各司其职

  • Model: 只关心数据和业务逻辑(厨师只管做饭)
  • View: 只关心界面显示(顾客只管看和点餐)
  • Presenter: 协调两者(服务员传递信息)

2. 易于测试

java 复制代码
// 可以单独测试Presenter,不需要Android环境
@Test
public void testPresenter() {
    // 创建模拟的View
    CustomerView mockView = mock(CustomerView.class);
    Waiter waiter = new Waiter(mockView);
    
    // 测试点餐逻辑
    waiter.takeOrder("宫保鸡丁");
    
    // 验证View被正确调用
    verify(mockView).showLoading(anyString());
}

3. 代码可维护性高

当需要修改界面时,只需要改动View;

当需要修改业务逻辑时,只需要改动Model;

它们互不影响!

总结

通过这个餐厅的故事,我们可以看到MVP架构就像一家组织良好的餐厅:

  • 顾客 (View) 不需要知道菜品怎么做,只需要表达需求看结果
  • 服务员 (Presenter) 不亲自做饭,但协调整个流程
  • 厨师 (Model) 专心做饭,不直接面对顾客

这种架构让我们的代码更加清晰、可维护、可测试,就像一家运转良好的餐厅一样高效有序!

相关推荐
编程之路从0到18 分钟前
React Native新架构之Android端初始化源码分析
android·react native·源码阅读
行稳方能走远9 分钟前
Android java 学习笔记2
android·java
编程之路从0到132 分钟前
React Native 之Android端 Bolts库
android·前端·react native
爬山算法34 分钟前
Hibernate(38)如何在Hibernate中配置乐观锁?
android·java·hibernate
行稳方能走远1 小时前
Android java 学习笔记 1
android·java
zhimingwen1 小时前
【開發筆記】修復 macOS 上 JADX 啟動崩潰並實現快速啟動
android·macos·反編譯
longxibo2 小时前
mysql数据快速导入doris
android·大数据·python·mysql
十六年开源服务商2 小时前
WordPress网站模板设计完整指南
android
summerkissyou19872 小时前
Android13-Bluetooth-代码目录介绍
android·蓝牙