我正在努力思考如何更好地设计我正在工作的系统。
假设这是一个类似于当铺的应用程序。我已经将购买和转售的流程分解为一种称为ExecutionStrategy的东西。这个应用程序中有四个ExecutionStrategy实现:注册客户、竞价和购买、定价和发布到商店。
每种策略都有一个基本步骤,包括主要的执行工作流程和记录我们在数据存储中所做的工作。
除了这些投标和采购以及定价之外,在我们可以在执行工作流程中做任何事情之前,我们都需要咨询专家。
这就是我对我想要在设计方面做出的决定感到有点困惑的地方。看起来好像有三个选项,我不太确定哪一个是最正确的。1)使用类似于带有ExecutionStrategyWithConsultation的ExecutionStrategy的东西来扩展执行策略,它用咨询阶段包装了策略的执行工作流。2)为ExecutionStrategy创建一个装饰器模式,并使用ConsultationServiceDecorator之类的东西对其进行扩展。3)在采购/招投标和定价的实现中创建成员变量,随时调用咨询服务,并围绕该服务提供接口。
我将在下面概述设计。
一些注意事项:
T consultOn(T item)
以上每种方法的优缺点:
- PRO: We can have access to a protected ConsultationService variable in the code
- PRO: We have an understanding from reading the code that a, say, `PurchasingExecutionStrategy extends ExecutionStrategyWithConsultation`, so we know a bit about what kind of workflow it is just from that.
- CON: This seems to break the "composition over inheritance" pattern. We are using inheritance for storing member variables.
- CON: The service returns a whole new object, so after the first line of code when we make the call to the service, we are dealing with an entirely different object than the one passed originally.
- PRO: We are more closely conforming with the composition over inheritance principal.
- PRO: We can enforce that the service is called first, and pass that new object to the main workflow, so it only executes its main workflow on the object passed.
- CON: I have not figured out a way to design this in a way to allow for potentially multiple or any time service calls.
- CON: When looking at the code, we lose the knowledge gained from `PurchasingExecutionStrategy extends ExecutionStrategyWithConsultation`, unless we look at where `PurchasingExecutionStrategy` is actually being instantiated as a constructor arg of `ConsultationServiceDecorator`
- PRO: Same pros as #1. Easy to understand fully what code is doing without digging.
- CON: Same cons as #1. Cannot enforce order. Execution deals with inheritenly different object than the one passed.
- CON: If we need to make multiple calls in the same workflow, this would be very slow due to service speed and no cache.
每种方法的示例:
//Number 1
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public interface ConsultationService {
public StoreItem consultOn (StoreItem item);
}
public abstract class ExecutionStrategyWithConsultation implements ExecutionStrategy<StoreItem> {
protected ConsultationService consultationService;
}
public class ListingExecutionStrategy extends ExecutionStrategyWithConsultation {
public StoreItem execute(StoreItem item) {
if (item.hasDirectBuyer()) { //hasDirectBuyer is populated by ConsultationService
item.sellTo = item.directBuyer.getId();
} else {
//no direct buyer
SuggestedPriceRange priceRange = item.getConsultationPriceRange(); //consultationPriceRange is populated by ConsultationService
item.priceRange = priceRange;
item.listToWebsite = true;
}
return item;
}
}
//Number 2
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public abstract class ExecutionStrategyDecorator<T> implements ExecutionStrategy<T>{
protected final ExecutionStrategy<T> executionStrategy;
public ExecutionStrategyDecorator(ExecutionStrategy<T> execStrategy) {
executionStrategy = execStrategy;
};
}
public class ExecutionStrategyWithConsultation extends ExecutionStrategyDecorator<StoreItem> {
protected ConsultationService consultationService;
public ExecutionStrategyWithConsultation(ExecutionStrategy<StoreItem> execStrat, ConsultationService service) {
super(execStrat);
consultationService = service;
}
public StoreItem execute(StoreItem item) {
StoreItem itemAfterConsultation = consultationService.consultOn(item);
return execStrategy.execute(itemAfterConsultation);
}
}
public class ListingExecutionStrategy implements ExecutionStrategy<StoreItem> {
public StoreItem execute(StoreItem item) {
if (item.hasDirectBuyer()) { //hasDirectBuyer is populated by ConsultationService
item.sellTo = buyer.getId();
} else {
//no direct buyer
SuggestedPriceRange priceRange = item.getConsultationPriceRange(); //consultationPriceRange is populated by ConsultationService
item.priceRange = priceRange;
item.listToWebsite = true;
}
return item;
}
}
public class ListingExecutionStrategyFactory {
public ExecutionStrategy instantiate() {
return new ExecutionStrategyWithConsultation(new ListingExecutionStrategy(), new ConsultationServiceImpl());
}
}
//Number 3
public interface ExecutionStrategy<T> {
/**
* Perform the main execution workflow
*/
public T execute(T item);
}
public interface ConsultationService {
public DirectBuyer getDirectBuyerIfExists(StoreItemType itemType);
public SuggestedPriceRange getSuggestedPriceRange(StoreItem item);
}
public class ListingExecutionStrategy implements ExecutionStrategy<StoreItem> {
ConsultationService service;
public PurchasingExecutionStrategy(ConsultationService consultService) {
service = ConsultationService;
}
public StoreItem execute(StoreItem item) {
DirectBuyer buyer = service.getDirectBuyerIfExists(item.getItemType())
if (Optional.ofNullable(buyer).isPresent()) {
item.sellTo = buyer.getId();
return item;
} else {
//no direct buyer
SuggestedPriceRange priceRange = service.getSuggestedPriceRange(item);
item.priceRange = priceRange;
item.listToWebsite = true;
return item;
}
}
}
感谢您的投入。感谢你的帮助。
https://stackoverflow.com/questions/56224883
复制相似问题