上一篇地址:持续总结中!2024年面试必问 20 道设计模式面试题(六)-CSDN博客
十三、状态模式(State Pattern)和策略模式(Strategy Pattern)有何区别?
状态模式(State Pattern)和策略模式(Strategy Pattern)都是行为型设计模式,它们提供了不同的方法来处理对象的行为变化。以下是两种模式的主要区别:
状态模式(State Pattern):
状态模式允许一个对象在其内部状态改变时改变它的行为,看起来好像改变了其类。它主要用于实现状态机,即行为随状态改变而变化的场景。
特点:
- 状态模式关注对象的状态以及状态之间的转换。
- 状态模式通常用于封装复杂的条件语句(如基于状态的 if-else 或 switch-case 语句)。
组成部分:
- 状态接口(State):定义了所有具体状态共有的行为。
- 具体状态(Concrete State):实现状态接口,定义具体的状态行为和状态转换逻辑。
- 上下文(Context):维护当前状态,并提供给客户端使用。
使用场景:
- 当一个对象的行为依赖于它的状态,并且状态在运行时会改变时。
策略模式(Strategy Pattern):
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换,算法的变化不会影响到使用算法的客户。
特点:
- 策略模式关注算法或行为的家族,以及它们之间的互换性。
- 策略模式通常用于替代复杂的条件语句,通过定义一系列的策略来实现行为的变化。
组成部分:
- 策略接口(Strategy):定义了所有策略共有的接口。
- 具体策略(Concrete Strategy):实现策略接口,定义具体的算法或行为。
- 上下文(Context):配置一个策略对象,通过这个策略对象来执行算法。
使用场景:
- 当需要在运行时选择使用不同的算法或行为时。
状态模式与策略模式的区别:
-
关注点不同:
- 状态模式关注的是对象的状态以及状态之间的转换。
- 策略模式关注的是算法或行为的家族,以及它们之间的互换性。
-
使用目的不同:
- 状态模式用于根据对象的状态来改变行为,实现状态机。
- 策略模式用于在运行时根据不同的策略来改变行为,实现算法的动态选择。
-
状态与策略的区别:
- 状态通常与对象的属性或环境有关,而策略通常与解决问题的方法有关。
-
上下文的不同:
- 在状态模式中,上下文维护一个状态对象,该状态对象决定了对象的行为。
- 在策略模式中,上下文维护一个策略对象,该策略对象定义了对象的行为。
-
变化频率不同:
- 状态模式中的状态转换通常是由于对象的属性或环境发生变化。
- 策略模式中的策略变化通常是由于外部条件或用户选择。
-
实现方式不同:
- 状态模式通常通过状态对象来封装状态转换逻辑。
- 策略模式通常通过策略对象来封装算法或行为。
-
可扩展性不同:
- 状态模式在添加新状态时可能需要修改上下文类,因为状态转换逻辑可能依赖于上下文。
- 策略模式在添加新策略时不需要修改上下文类,因为策略是独立的,上下文只是使用策略。
总结来说,状态模式和策略模式虽然都可以改变对象的行为,但它们的关注点、使用目的、实现方式和可扩展性都有所不同。状态模式适用于行为随状态变化的场景,而策略模式适用于需要在运行时动态选择算法或行为的场景。
十四、请描述备忘录模式(Memento Pattern)及其使用场景。
备忘录模式(Memento Pattern),也称为备忘录对象模式,是一种行为设计模式,用于在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便之后可以恢复该状态。
备忘录模式的组成部分:
- 发起人(Originator):负责创建一个备忘录,用以记录当前对象的状态,并且可以恢复到先前的状态。
- 备忘录(Memento):存储发起人对象的内部状态,并且可以防止其他对象访问这些状态。
- 负责人(Caretaker):负责保存备忘录,但是不能对备忘录内容进行操作或检查。
备忘录模式的工作原理:
- 发起人对象在关键的时刻创建一个备忘录对象,将自身的状态存储在其中。
- 发起人对象可以继续变化,备忘录对象保存了创建时刻的状态。
- 当需要恢复到之前的状态时,发起人对象可以从备忘录对象中读取之前的状态信息,恢复到那个状态。
备忘录模式如何使用:
- 创建备忘录:发起人对象在关键状态时创建一个备忘录。
- 保存备忘录:负责人对象保存这个备忘录,可能将其存储在列表或其他结构中。
- 恢复状态:当需要回退到之前的状态时,发起人对象从负责人那里获取备忘录,并恢复其状态。
使用场景:
备忘录模式特别适用于以下情况:
- 当需要提供一个可以恢复到之前状态的功能,比如“撤销”操作。
- 当不希望外界直接获取对象的内部状态,同时又需要保存对象的状态时。
- 当对象的当前状态占用大量资源,而通过备忘录可以减少资源消耗时。
代码示例(伪代码):
// 备忘录接口
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// 负责人
class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public void addMemento(Memento memento) {
mementoList.add(memento);
}
public Memento getMemento(int index) {
return mementoList.get(index);
}
}
// 客户端代码
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State 1");
caretaker.addMemento(originator.saveStateToMemento());
originator.setState("State 2");
// ... 其他操作 ...
// 撤销到之前的状态
originator.getStateFromMemento(caretaker.getMemento(0));
// originator 的状态现在是 "State 1"
在这个示例中,Originator
类负责创建备忘录,并可以保存和恢复状态。Memento
类负责存储状态信息。Caretaker
类负责保存备忘录对象,可以管理多个备忘录,例如实现撤销栈。客户端代码通过使用这些类来实现状态的保存和恢复。通过这种方式,备忘录模式提供了一种在不破坏封装性的情况下保存和恢复对象状态的方法。