基于设计模式实现运行时对象引用切换:文本型星巴克模拟器屏幕切换问题
用状态模式搞定星巴克模拟器的屏幕切换问题
嘿,你的需求正好契合**状态模式(State Pattern)**的核心思想——把每个屏幕的行为和切换逻辑封装在各自的类里,让Frame只负责管理当前屏幕、分发事件,不用再堆一堆判断逻辑。这样不仅代码更清晰,后续加新屏幕也不用动核心的Frame类,扩展性拉满。
我给你拆解下具体的实现方案:
1. 先给IScreen接口补全关键方法
首先得让IScreen接口具备处理触摸事件并返回下一个屏幕的能力,这样每个屏幕才能自己决定切换逻辑:
public interface IScreen { // 处理触摸坐标,返回要切换到的下一个屏幕(返回this表示不切换) IScreen handleTouch(int x, int y); // 屏幕渲染方法,每个屏幕自己实现渲染逻辑 void render(); }
2. 让每个屏幕类自己管切换逻辑
比如你的初始屏幕MyCards,把它的触摸区域对应的切换逻辑直接写在类里:
public class MyCards implements IScreen { // 可以把按钮区域封装成常量,可读性更高 private static final Rect MENU_BUTTON = new Rect(80, 180, 120, 220); @Override public IScreen handleTouch(int x, int y) { // 判断是否点击了跳转到Menu的区域 if (MENU_BUTTON.contains(x, y)) { return new Menu(); } // 点击其他区域就留在当前屏幕 return this; } @Override public void render() { System.out.println("=== 我的卡片 ==="); System.out.println("点击[80-120, 180-220]区域进入菜单"); } }
再举个Menu屏幕的例子,它可以处理回到MyCards或者跳转到Payment的逻辑:
public class Menu implements IScreen { private static final Rect BACK_BUTTON = new Rect(30, 30, 70, 70); private static final Rect PAYMENT_BUTTON = new Rect(130, 130, 170, 170); @Override public IScreen handleTouch(int x, int y) { if (BACK_BUTTON.contains(x, y)) { return new MyCards(); } else if (PAYMENT_BUTTON.contains(x, y)) { return new Payment(); } return this; } @Override public void render() { System.out.println("=== 菜单 ==="); System.out.println("点击[30-70, 30-70]返回我的卡片"); System.out.println("点击[130-170, 130-170]进入支付"); } }
3. 简化Frame类的逻辑
现在Frame只需要把触摸事件丢给当前屏幕,然后更新current引用就行,不用自己做任何判断:
public class Frame implements IFrame { private IScreen current = new MyCards(); // 处理触摸事件的方法(你原来的"tou..."应该就是这个) public void touch(int x, int y) { IScreen nextScreen = current.handleTouch(x, y); if (nextScreen != current) { // 只有当屏幕变化时才更新 current = nextScreen; current.render(); // 切换后重新渲染新屏幕 } } // 初始化时渲染初始屏幕 public void init() { current.render(); } // 其他无关代码省略 }
为啥这个方案好用?
- 各司其职:Frame只管屏幕的生命周期,每个屏幕只管自己的渲染和切换,符合单一职责原则。
- 易扩展:以后加新屏幕(比如OrderHistory),只需要实现IScreen接口,完全不用改Frame的代码。
- 逻辑清晰:切换逻辑和屏幕绑定,不用在Frame里写一堆if-else判断各种坐标,维护起来超轻松。
可选小优化
- 如果屏幕不需要每次都新建实例,可以用单例模式复用对象,减少内存开销。
- 把
Rect类封装成通用工具类,方便所有屏幕使用坐标判断。
内容的提问来源于stack exchange,提问作者Paul Roman
相关产品推荐
相关产品推荐

