[英]Implementing the inheritance hierarchy in the State Pattern
I have a design which is very similar to this:我有一个与此非常相似的设计:
Here NewOrder , Registered & Granted all have the common methods AddOrderline()
and Cancel()
, so refactoring both methods to a parent class is easy.这里NewOrder 、 Registered和Granted都有公共方法AddOrderline()
和Cancel()
,因此将这两种方法重构为父类很容易。
The problem occurs when I want to Cancel
a Shipped
line (currently not shown in the figure).当我想Cancel
已Shipped
行(当前未在图中显示)时会出现问题。
Since a Shipped line doesn't support AddOrderline()
then I'll need to break the parent class for NewOrder , Registered & Granted into 2 class one for the Cancel()
and another for AddOrderline()
.由于Shipped线路不支持AddOrderline()
因此我需要将NewOrder 、 Registered & Granted的父类分解为Cancel()
和AddOrderline()
。
Now NewOrder
must extend 2 parent class to get the 2 functions.现在NewOrder
必须扩展 2 个父类才能获得 2 个函数。
Notes笔记
I would consider the separation of the interface from the implementation.我会考虑将接口与实现分离。 eg in Java例如在 Java 中
interface Cancellable {
void cancel();
}
interface Shippable{
void ship();
}
etc.等等。
public class NewState implements Cancellable, Shippable {
public void cancel() { ... }
public void ship() { ... }
}
If you have an underlying private State, it can implement all the required interfaces, and your public States need only delegate those supported states.如果你有一个底层的私有状态,它可以实现所有需要的接口,而你的公共状态只需要委托那些支持的状态。 eg例如
public class UnderlyingState implements Cancellable, Shippable ... {
public void cancel() { ... }
public void ship() { ... }
}
public class ShippableState implements Shippable {
private UnderlyingState ustate = new UnderlyingState();
public void cancel() {
// you can *only* cancel this
ustate.cancel();
}
}
In the above you'd probably need to return a new state object (rather than void
) and have your Order
adopt that new state.在上面,您可能需要返回一个新的状态对象(而不是void
)并让您的Order
采用该新状态。 The UnderlyingState
object would enforce some state machine. UnderlyingState
对象将强制执行某种状态机。
The headache with this is that as your number of states increase, your interfaces and implementation increases too.令人头疼的是,随着状态数量的增加,您的接口和实现也会增加。
First, you'll need a state manager to handle states:首先,您需要一个状态管理器来处理状态:
<?php
class StateManager
{
protected $states = array();
public function registerState(StateInterface $state)
{
$this->states[$state->getName()] = $state;
}
public function getState($state)
{
if (!array_key_exists($state, $this->states)) {
throw new InvalidArgumentException();
}
return $this->states[$state];
}
}
Then you have an order manager that can perform actions against orders:然后你有一个订单管理器,可以对订单执行操作:
<?php
class OrderManager
{
protected $stateManager;
public function ship(OrderInterface $order)
{
try {
$this->stateManager->getState($order->getState())->ship($order);
} catch (OperationNotAllowedException $exception) {
// However you want to handle the fact that the state can't be shipped
}
}
}
An exception that gets thrown if an order can't take an action in a certain state:如果订单在特定状态下无法执行操作,则会引发异常:
<?php
class OperationNotAllowedException extends Exception
{
}
The interface for a state:状态接口:
<?php
interface StateInterface
{
public function getName();
// Then your normal functions
public function ship(OrderInterface $order);
public function cancel(OrderInterface $cancel);
public function addOrderLine(OrderInterface $order);
public function refund(OrderInterface $order);
}
Now, when you setup your application:现在,当您设置应用程序时:
$newOrderState = new NewState($database, $otherdependencies);
$stateManager->registerState($newOrderState);
Your order object simply returns a string name for the state it's in, that matches what one of the state's getName
methods returns.您的订单对象仅返回其所在状态的字符串名称,该名称与该状态的getName
方法之一返回的内容相匹配。
This method also allows for easy mocking and testing (which is important for any application, but especially e-commerce where you are handling people's money and products).这种方法还允许轻松模拟和测试(这对于任何应用程序都很重要,尤其是在处理人们的金钱和产品的电子商务)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.