首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >什么时候使用成员变量还是按组合进行设计?

什么时候使用成员变量还是按组合进行设计?
EN

Stack Overflow用户
提问于 2019-05-21 00:30:11
回答 1查看 57关注 0票数 0

我正在努力思考如何更好地设计我正在工作的系统。

假设这是一个类似于当铺的应用程序。我已经将购买和转售的流程分解为一种称为ExecutionStrategy的东西。这个应用程序中有四个ExecutionStrategy实现:注册客户、竞价和购买、定价和发布到商店。

每种策略都有一个基本步骤,包括主要的执行工作流程和记录我们在数据存储中所做的工作。

除了这些投标和采购以及定价之外,在我们可以在执行工作流程中做任何事情之前,我们都需要咨询专家。

这就是我对我想要在设计方面做出的决定感到有点困惑的地方。看起来好像有三个选项,我不太确定哪一个是最正确的。1)使用类似于带有ExecutionStrategyWithConsultation的ExecutionStrategy的东西来扩展执行策略,它用咨询阶段包装了策略的执行工作流。2)为ExecutionStrategy创建一个装饰器模式,并使用ConsultationServiceDecorator之类的东西对其进行扩展。3)在采购/招投标和定价的实现中创建成员变量,随时调用咨询服务,并围绕该服务提供接口。

我将在下面概述设计。

一些注意事项:

  • ConsultationService非常非常慢。缓存在这里并不是一个真正的选项,因为数据的格式非常松散,而且我们不希望仅仅为了this.
  • ConsultationService返回一个与给定内容匹配的对象而创建文档数据存储。因此,它最终得到了一个看起来像T consultOn(T item)
  • There的方法,希望在执行工作流中的任何时候调用ConsultationService。目前唯一的用例是在主流之前调用服务,但这不一定是目前唯一的用例。

以上每种方法的优缺点:

  1. 直接扩展ExecutionStrategy:

代码语言:javascript
复制
- 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. 

  1. 创建装饰器:

代码语言:javascript
复制
- 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`

  1. 使用以下接口创建成员变量:

代码语言:javascript
复制
- 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.  

每种方法的示例:

代码语言:javascript
复制
//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;
    }
}

代码语言:javascript
复制
//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());
    }
}

代码语言:javascript
复制
//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;
      }
    }
}

感谢您的投入。感谢你的帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-21 03:30:08

作为ConsultationService的替代方案,您可以考虑构建ExecutionService实例链,以允许创建复杂的处理场景:

代码语言:javascript
复制
public interface ExecutionStrategy<T> {
    public T execute(T item);
}


public interface ExecutionStrategyChain<T> extends ExecutionStrategy<T> {
    public static <T> ExecutionStrategyChain<T> newInstance(ExecutionStrategy<T> executionStrategy) {
        return new ExecutionStrategyChainImpl<T>(executionStrategy); 
    }

    public ExecutionStrategyChain<C> chainTo(ExecutionStrategy<C> executionStrategy);
}


public abstract class AbstractExecutionStrategyChain<T> implements ExecutionStrategyChain<T> {
    protected AbstractExecutionStrategyChain() {
        this(null);
    }


    public abstract T execute(T item);


    public ExecutionStrategyChain<T> chainTo(ExecutionStrategy<T> executionStrategy) {
        return new ExecutionStrategyChainImpl<T>(this, executionStrategy);
    }
}


public final class ExecutionStrategyChainImpl<T> extends AbstractExecutionStrategyChain<T> {

    private final ExecutionStrategy<T> firstExecutionStrategy;
    private final Executionstrategy<T> secondExecutionStrategy;

    public ExecutionStrategyChainImpl(ExecutionStrategy<T> first, ExecutionStrategy<T> second) {
        if(first == null) throw new NullPointerException();
        this.firstExecutionStrategy = first;
        this.secondExecutionStrategy = second;
    }

    public ExecutionStrategyChainImpl(ExecutionStrategy<T> first) {
        this(first, null);
    }

    @Override
    public final T execute(T item) {
        if(item == null) {
            return null;
        }

        T result = firstExecutionStrategy.execute(item);
        if(result != null && secondExecutionStrategy != null) {
            result = secondExecutionStrategy.execute(result);
        }
        return result;
    }
}


public class PreProcessor<T> implements ExecutionStrategy<T> {

    public PreProcessor() {
    }

    @Override
    public T execute(T item) {
       //Do some pre-processing of item
       return item;
    }
}


public class PostProcessor<T> implements ExecutionStrategy<T> {

    public PostProcessor() {
    }

    @Override
    public T execute(T item) {
       //Do some post-processing of item
       return item;
    }
}


public class MyNormalProcessor<T> extends AbstractExecutionStrategyChain<T> {

    public MyNormalProcessor() {
    }

    @Override
    public T execute(T item) {
       //Do something normal with the item
       return item;
    }
}


public static final ExecutionStrategy<StoreItem> COMPLEX_EXECUTION_STRATEGY = 
    ExecutionStrategyChain<StoreItem>.newInstance(new PreProcessor<StoreItem>())
                                     .chainTo(new MyNormalProcessor<StoreItem>())
                                     .chainTo(new PostProcessor<StoreItem>());
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56224883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档