gpt4 book ai didi

c++ - 如何根据对象的状态更改对象的接口(interface)?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:21:26 26 4
gpt4 key购买 nike

给定一个具有很多状态的相当复杂的对象,是否有一种模式可以根据该状态公开不同的功能?

举个具体的例子,想象一个 Printer 对象。

  • 最初,该对象的界面允许您查询打印机的功能、更改纸张方向等设置以及开始打印作业。

  • 启动打印作业后,您仍然可以查询,但不能启动另一项作业或更改某些打印机设置。你可以开始一个页面。

  • 启动页面后,您可以发出实际的文本和图形命令。您可以“完成”页面。您不能同时打开两个页面。

  • 某些打印机设置只能在页面之间更改。

一个想法是让一个 Printer 对象具有大量方法。如果您在不适当的时间调用方法(例如,尝试更改页面中间的纸张方向),调用将失败。也许,如果您跳过序列并开始发出图形调用,Printer 对象可能会隐式调用 StartJob()StartPage()方法根据需要。这种方法的主要缺点是调用者不太容易。界面可能会让人不知所措,并且顺序要求不是很明显。

另一个想法是将事物分解为单独的对象:PrinterPrintJobPagePrinter 对象公开查询方法和 StartJob() 方法。 StartJob() 返回一个 PrintJob 对象,该对象具有 Abort()StartPage() 和用于更改的方法可更改的设置。 StartPage() 返回一个 Page 对象,该对象提供用于进行实际图形调用的接口(interface)。这里的缺点是机制之一。如何在不放弃对该对象生命周期的控制的情况下公开该对象的接口(interface)?如果我给调用者一个指向 Page 的指针,我不希望他们删除 它,并且在他们返回第一个之前我不能给他们另一个。

不要太在意打印示例。我正在寻找关于如何根据对象的状态呈现不同界面的一般性问题。

最佳答案

是的,它叫做 state pattern .

一般的想法是您的 Printer 对象包含一个 PrinterState 对象。 Printer 对象上的所有(或大多数)方法只是委托(delegate)给包含的 PrinterState。然后,您将拥有多个 PrinterState 类,它们以不同的方式实现方法,具体取决于在该状态下允许/不允许的内容。 PrinterState 实现也将提供一个“钩子(Hook)”,允许它们将 Printer 对象的当前状态更改为另一个状态。

这是一个包含几个状态的示例。这看起来很复杂,但如果你有复杂的特定于状态的行为,它实际上会使代码和维护变得更容易:

public abstract class PrinterState {
private PrinterStateContext stateContext;

public PrinterState( PrinterStateContext context ) {
stateContext = context;
}

void StartJob() {;}
}

public class PrinterStateContext {
public PrinterState currentState;
}


public class PrinterReadyState : PrinterState {

public PrinterReadyState( PrinterStateContext context ) {
super(context);
}

void StartJob() {
// Do whatever you do to start a job..

// Switch to "printing" state.
stateContext.currentState = new PrinterPrintingState(stateContext);
}
}

public class PrinterPrintingState : PrinterState {

public PrinterPrintingState( PrinterStateContext context ) {
super(context);
}

void StartJob() {
// Already printing, can't start a new job.
throw new Exception("Can't start new job, already printing");
}
}


public class Printer : IPrinter {
private PrinterStateContext stateContext;

public Printer() {
stateContext = new PrinterStateContext();
stateContext.currentState = new PrinterReadyState(stateContext);
}

public void StartJob() {
stateContext.currentState.StartJob();
}
}

关于c++ - 如何根据对象的状态更改对象的接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1477197/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com