英文:
Best way to evaluate a condition set on N objects (depending on their state)
问题
考虑两个对象:
1)Order
2)Bag
每个对象都有一个状态字段:
Order:[INITIALIZED,PICKED_UP,IN_TRANSIT,DELIVERED]
Bag:[INITIALIZED,ACQUIRED,DAMAGED,DELIVERED]
最后,每个订单都有一组分配的包裹。
在更新Order
对象的状态时,我需要检查是否满足N
个条件,例如:当将Order
状态更新为"PICKED_UP"
时,所有相关联的包裹必须依次处于"ACQUIRED"
状态。
这是我能提供的最简单的示例,但我正在寻找关于以下主题的一些提示:
1)编写易于维护的代码,而无需重写整套条件(有时条件可能是嵌套的!)
2)避免冗长的“if,else if,else if...”
3)将涉及这些评估的所有逻辑保持在同一个类中,以便让阅读代码的人可以快速了解代码的目的,并在需要时了解如何实现新的逻辑。
希望问题不是太泛泛无边!
谢谢!
英文:
Considering two objects:
Order
Bag
And each object has a status field:
Order: [INITIALIZED, PICKED_UP, IN_TRANSIT, DELIVERED]
Bag: [INITIALIZED, ACQUIRED, DAMAGED, DELIVERED]
Finally, each order has a set of bags assigned.
When updating the status of an Order
object, I need to check that N
conditions are respected, like: when updating an Order
status to "PICKED_UP"
, all the bags associated must be in turn, in the "ACQUIRED"
status.
This is the simplest example that I can do, but I'm looking for some hints about these topics:
- Writing code that can be easily maintained, without rewriting the whole set of conditions (conditions can be nested sometimes!)
- Avoid long lists of "if, else if, else if...."
- Keeping all the logic involved into these evaluations in the same class, in order to give to the person that is reading the code, a quick glance about the purpose of the code, and in case, how to implement a new logic.
I hope that the question is not too generic!
Thank you!
答案1
得分: 1
以下是翻译好的内容:
public static class Order
{
public List<Bag> bags = new ArrayList<>();
public OrderStatus currentStatus = OrderStatus.INITIALIZED;
public void moveOrderToStatus(OrderStatus status)
{
if(!status.isValidStatusForOrder(this)) throw new IllegalStateException("Invalid status");
currentStatus = status;
}
}
public static class Bag
{
public BagStatus status = BagStatus.INITIALIZED;
}
public enum OrderStatus
{
INITIALIZED(order -> { throw new UnsupportedOperationException(); }),
PICKED_UP(order -> { return order.bags.stream().allMatch(bag -> bag.status == BagStatus.ACQUIRED); }),
IN_TRANSIT(order -> { throw new UnsupportedOperationException(); }),
DELIVERED(order -> { throw new UnsupportedOperationException(); });
private final OperationValidator validator;
OrderStatus(OperationValidator validator){ this.validator = validator; }
public boolean isValidStatusForOrder(Order order){ return validator.isValid(order); }
}
public enum BagStatus { INITIALIZED, ACQUIRED, DAMAGED, DELIVERED }
@FunctionalInterface
public interface OperationValidator{ boolean isValid(Order order); }
作为另一种选择,可以将订单状态建模为不同的类。例如:使用InitializedOrder、PickedUpOrder、InTransitOrder等来表示不同的订单阶段。这可能会更容易地防止订单被错误使用/进入无效逻辑。
英文:
One way to model this is to delegate the decision of whether an order is allowed to be of a certain state to that state. In the below, the OrderStatus enum has method 'isValidStatusForOrder(Order)' which returns true if the order can be moved to that status. Then the Order class has method moveOrderToStatus which first checks if it can be moved before moving the status.
public static class Order
{
public List<Bag> bags = new ArrayList<>();
public OrderStatus currentStatus = OrderStatus.INITIALIZED;
public void moveOrderToStatus(OrderStatus status)
{
if(!status.isValidStatusForOrder(this)) throw new IllegalStateException("Invalid status");
currentStatus = status;
}
}
public static class Bag
{
public BagStatus status = BagStatus.INITIALIZED;
}
public enum OrderStatus
{
INITIALIZED(order -> { throw new UnsupportedOperationException(); }),
PICKED_UP(order -> { return order.bags.stream().allMatch(bag -> bag.status == BagStatus.ACQUIRED); }),
IN_TRANSIT(order -> { throw new UnsupportedOperationException(); }),
DELIVERED(order -> { throw new UnsupportedOperationException(); });
private final OperationValidator validator;
OrderStatus(OperationValidator validator){ this.validator = validator; }
public boolean isValidStatusForOrder(Order order){ return validator.isValid(order); }
}
public enum BagStatus { INITIALIZED, ACQUIRED, DAMAGED, DELIVERED }
@FunctionalInterface
public interface OperationValidator{ boolean isValid(Order order); }
As an alternative, order state may be modelled in different classes. Ex: represent the different order stages using InitializedOrder, PickedUpOrder, InTransitOrder, etc. This may make it easier to prevent orders from being used improperly/entering invalid logic.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论