Oop 说明符合Liskov的设计模式

Oop 说明符合Liskov的设计模式,oop,architecture,liskov-substitution-principle,state-pattern,Oop,Architecture,Liskov Substitution Principle,State Pattern,我正在设计一个订单系统,状态设计模式似乎很合适,因为订单可以更改其状态,从而更改订单允许的功能。下面是我的基本类图: 我不喜欢这种方法,因为客户端看不到方法是否受支持,并且违反了Liskov原则。我在下面创建了一个备选方案: 我更喜欢这一点,但客户端仍然必须检查是否支持某个方法。但是他们仍然可以调用不受支持的方法并获得异常。这是否仍然违反了里斯科夫原则 是否有一种更好的设计符合Liskov,并且可以防止用户为特定状态调用无效方法?您显示的不是状态模式。当对象的内部状态改变时,状态模式会改变对

我正在设计一个订单系统,状态设计模式似乎很合适,因为订单可以更改其状态,从而更改订单允许的功能。下面是我的基本类图:

我不喜欢这种方法,因为客户端看不到方法是否受支持,并且违反了Liskov原则。我在下面创建了一个备选方案:

我更喜欢这一点,但客户端仍然必须检查是否支持某个方法。但是他们仍然可以调用不受支持的方法并获得异常。这是否仍然违反了里斯科夫原则


是否有一种更好的设计符合Liskov,并且可以防止用户为特定状态调用无效方法?

您显示的不是状态模式。当对象的内部状态改变时,状态模式会改变对象的行为。例如,灯光开关可以在切换灯光时打开或关闭灯光,具体取决于其状态(同一方法中的不同行为)

使用这个顺序接口(4种不同的方法),我看不到引入状态模式的任何好处。这只会无缘无故地使事情复杂化。但我不知道所有的细节,所以下一步该怎么办取决于你


查看此链接以查看状态模式实施的示例

我不明白您所说的“无法查看是否支持某个方法”是什么意思。具体的OrderState都将实现OrderState方法。当该状态当前不允许该操作时,其中一些将引发异常。这并没有违反LSP imo。同样,我不认为这有什么不同,当你不直接提出一个不支持的Dopex,你首先调用一个can*方法,然后提出它。在我看来,允许订单的任何消费者调用can*方法更糟糕,因为它将责任转移到订单对象之外。在类图1中,客户端无法检测操作是否对特定状态有效。那么就没有办法知道是否应该显示一个支付按钮或一个取消按钮。在我对LSP的理解中,抛出notSupportedException是破坏LSP的常见方法。这是因为子类型不执行所说的操作,因此子类型不能替换其基类型。具体的
OrderStates
都将实现
OrderState
接口,从而实现其方法。如果可能的话,所有这些方法都将通过接口契约潜在地引发异常。因此,您可以用另一个子类型替换OrderState的任何具体子类型。因此,您不会违反Liskov的替换原则。您可以使用完全相同的模式来绘制按钮。顺便说一句,只需将按钮渲染器传递给OrderState,并让它从具体的OrderState返回正确的按钮,例如,确认将告诉按钮渲染器渲染付款按钮,等等。我查阅了LSP的定义“如果S是T的子类型,则T类型的对象可替换为S类型的对象(即,S类型的对象可替换为T类型的对象),而不改变该程序的任何期望属性(正确性、执行的任务等)。”“由于您正在对订单调用pay方法,并且您希望您正在支付订单,因此违反了正确性。取而代之的是,目前的国家将永远无法支付。因此,这将破坏系统的正确性。请特别注意,如果预期出现异常,则不会违反正确性。否则,任何引发异常的方法都会违反LSP。我之所以在设计中使用状态模式,是因为顺序改变了状态,这会改变其行为。如果我创建单独的order类,那么order在运行时无法更改其行为。你对不同的模式有什么建议吗?最简单的解决方案是一个带有4个diff方法的单阶模型,当对象处于不适当的状态时,当你试图使用一个方法时,它会抛出一个异常。通常,当我不知道所有细节时,我会选择最简单的解决方案,这将在以后更容易重构。但这完全取决于应用程序/代码中的订单使用情况。例如,如果您有一个带有一个
proceedToTheNextState
方法的订单界面,那么您可以创建4个状态:确认、取消、付款、发货,它们完成与该状态相关的所有工作,并转移到下一个状态。此外,您可能有许多不同的原因需要拆分订单行为逻辑。结果可能不是状态模式的精确实现。如果一切都是为了某个原因而完成的,那么一切都是好的。如果遵循子类中的接口和方法定义,就不能破坏LSP。