评估N个对象上设置的条件集的最佳方法(取决于它们的状态)

huangapple go评论72阅读模式
英文:

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:

  1. Order
  2. 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:

  1. Writing code that can be easily maintained, without rewriting the whole set of conditions (conditions can be nested sometimes!)
  2. Avoid long lists of "if, else if, else if...."
  3. 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&lt;Bag&gt; bags = new ArrayList&lt;&gt;();
		public OrderStatus currentStatus = OrderStatus.INITIALIZED;
		public void moveOrderToStatus(OrderStatus status)
		{
			if(!status.isValidStatusForOrder(this)) throw new IllegalStateException(&quot;Invalid status&quot;);
			currentStatus = status;
		}
	}

	public static class Bag
	{
		public BagStatus status = BagStatus.INITIALIZED;
	}

	public enum OrderStatus
	{
		INITIALIZED(order -&gt; { throw new UnsupportedOperationException(); }),
		PICKED_UP(order -&gt; { return order.bags.stream().allMatch(bag -&gt; bag.status == BagStatus.ACQUIRED); }),
		IN_TRANSIT(order -&gt; { throw new UnsupportedOperationException(); }),
		DELIVERED(order -&gt; { 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.

huangapple
  • 本文由 发表于 2020年9月25日 02:59:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/64052752.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定