备忘录模式能否使用多发起者?游戏状态存恢复方案咨询
1. 是否支持多个发起者共用同一Memento和Caretaker?
完全可以。备忘录模式的核心就是封装状态快照,并没有规则限制只能有一个发起者向同一个Memento写入或读取状态。只要你的Memento能容纳Game Engine和Game Window所有需要保存的状态,并且两个类都清楚自己该操作Memento里的哪部分数据,就能实现这个需求。
2. 这种设计是否合理?
得看你的实际场景来判断:
- 合理的情况:如果Game Engine和Game Window的状态属于同一游戏状态上下文(比如窗口的视角位置、UI面板状态,和游戏内玩家的位置、道具状态是强关联的,必须同时保存或恢复),这种方式能简化Caretaker的逻辑——只需要管理一个Memento实例,不用协调多个快照的保存时机。
- 需要谨慎的情况:如果两者状态是弱关联的(比如窗口大小是用户偏好设置,和游戏内进度完全无关),强行把它们塞到同一个Memento里会违反单一职责原则,导致Memento变得臃肿,后续维护起来很麻烦。
3. 其他可选方案
方案一:拆分多个Memento,同一Caretaker管理
给Game Engine和Game Window分别创建对应的Memento类(比如GameEngineMemento和GameWindowMemento),让Caretaker同时持有这两个Memento的实例。保存状态时,两个发起者各自生成自己的快照;恢复时,各自读取对应的Memento就行。这种方式状态划分清晰,符合单一职责,适合两者状态关联性弱的场景。
方案二:引入统一的状态持有者
创建一个GameState类,专门存储所有需要保存的状态——包括Game Engine里的Player数据、Game Window的UI或窗口变量。让Game Engine和Game Window都依赖这个GameState,此时GameState作为唯一的Originator,负责生成和恢复Memento,而Game Engine和Game Window只负责修改或读取GameState里的数据。这种方式彻底统一了状态管理,避免了多发起者的协调问题,是游戏开发里比较常用的做法。
方案三:使用组合式Originator
创建一个CompositeOriginator类,内部持有Game Engine和Game Window的引用。保存状态时,CompositeOriginator调用两个子发起者的保存方法,把各自的状态整合到一个Memento中;恢复时再拆分状态,传递给对应的子发起者。这种方式既保留了单一Memento的便利性,又让各个子发起者的状态逻辑保持独立,不会互相干扰。
内容的提问来源于stack exchange,提问作者InNeedOfHelp01

