我无法绕过基于状态的功能来处理我们目前正在构建的发票系统。系统将支持发票的计算,手动批准,打印和存档。
起初我以为我们应该使用State Pattern对此进行建模。发票将是上下文,它将打印,存档等委托给其当前分配的状态。
但这显然是一个坏主意,因为不同的状态(创建,批准,打印,存档)不应该支持相同的操作。例如,您不应该打印以前未经批准的发票。抛出不支持的操作的异常将违反LSP。我找到了这个问题的一般描述here。
有没有人有想法,如何恰当地实现这个?
答案 0 :(得分:1)
您基本上是在创建应用程序状态的工作流程,在每个州,发票上的可用操作都会发生变化。状态模式似乎不合适,但如果您还创建了一些必须在调用boolean canPrint()
之前使用的print()
之类的操作,您仍然可以使用它。如果print()
返回canPrint()
,则false
会签订合同,允许抛出异常。这样,子类就不会破坏该合同。另一个选择是拥有boolean tryPrint()
,只有在可以的情况下才能打印,并返回是否打印。
但是,如果州主要支持非重叠操作,那么状态模式可能不是解决方案。退一步寻找更好的方法,而不是试图使特定的模式适合您的问题。一种方法是创建一个单独的类,其中包含每个“状态”的必要操作:如CreatedInvoice
,ApprovedInvoice
等。这些类只有他们支持的操作。
答案 1 :(得分:0)
Chain of Responsibility Pattern可能会对您有所帮助。
添加部分并修复链接。
可以有Calculator,Approver,Printer和Archiver类,它们是处理程序类。这些可以从父抽象类重写processRequest()。 Invoice可以是传递给每个处理程序的processRequest()方法的类。这里使用模式的优点是可以动态添加更新的处理程序,并且可以轻松更改带有处理程序序列的链接。
答案 2 :(得分:0)
状态模式是否真的适合您的情况尚不确定,但如果不是,Liskov不是原因。在状态接口中可以定义某种“当前状态下的无效操作”异常,并且在子状态中执行此操作不会违反LSP。
GoF Design Patterns书中用于状态模式的经典示例是TCPConnection,它肯定在所有状态下都不支持或不合理操作。例如,您无法在已关闭的连接上进行传输。