构造函数过度注入和外观服务概念

时间:2018-07-25 08:36:18

标签: java design-patterns

我有一个非常简单的界面,用于管理业务建议的更新,特别是在每晚批处理过程中,每条记录都在此处提交(但可能在其他情况下使用)。 该接口在EJB 2.0 Bean中使用,该EJB 2.0 Bean提取记录并“循环”它们。 当心名称从意大利语翻译成英语,因此请避免可能的错误。我还简化了一些概念。

public interface ProposalUpdateService {
    void updateProposal(final ProposalFirstType proposal);
    void updateProposal(final ProposalSecondType proposal);
}

此接口的实现有很多依赖项:

public class ProposalUpdateDefaultService implements ProposalUpdateService {
    private final ComplexService complexService;
    private final OtherComplexService otherComplexService;

    private final ProposalStep<Proposal> stepOne;
    private final ProposalStep<Proposal> stepTwo;
    private final ProposalStep<ProposalTypeTwo> stepThree;
    private final ProposalStep<Proposal> stepFour;

    public ProposalUpdateDefaultService(
            final ComplexService complexService,
            final OtherComplexService otherComplexService,
            final YetAnotherComplexService yetAnotherComplexService,
            final SimpleService simpleService,
            final OtherSimpleService otherSimpleService,
            final YetAnotherSimpleService yetAnotherSimpleService,
            final Converter<ProposalTypeOne, ComplexServiceType> converterProposalTypeOne,
            final Converter<ProposalTypeTwo, OtherComplexServiceType> converterProposalTypeTwo) {
        this.complexService = complexService;
        this.otherComplexService = otherComplexService;

        stepOne = new StepOne(yetAnotherComplexService);
        stepTwo =
                new StepTwo(
                        complexService,
                        otherComplexService,
                        yetAnotherComplexService,
                        converterProposalTypeOne,
                        converterProposalTypeTwo);
        stepThree =
                new StepThree(
                        simpleService,
                        otherSimpleService,
                        yetAnotherSimpleService);
        stepFour = new StepFour();
    }

    ...

如您所见,该类封装了Proposal对象的更新,并且此过程分为四个阶段,每个阶段代表一个概念(例如“该建议是否应过期?”或“应该我会提高其状态吗?”)。在不同类型的Proposal之间,这四个阶段的排列方式可能不同。

这是这两个updateProposal方法的高度简化的实现:

@Override
public void updateProposal(final ProposalTypeOne proposal) {
   stepOne.process(proposal);
   stepTwo.process(proposal);

   if (...) {
      stepFour.process(proposal);
   }
}

@Override
public void updateProposal(final ProposalTypeTwo proposal) {
   stepOne.process(proposal);
   stepTwo.process(proposal);
   stepThree.process(proposal);
   stepFour.process(proposal);
}

两个私有字段

private final ComplexService complexService;
private final OtherComplexService otherComplexService;

用于助手私有方法。

如您所见,该类只是组织和委派工作,但是,它确实依赖于太多其他类。对于某些ProposalStep,也可以这样说。

在每个步骤中使用*Service(一个或多个)来从数据库中检索详细信息,更新相关条目等。

您会接受这种数量的依赖吗?
您将如何重构以简化操作?

我已经了解了Facade Service概念作为减少依赖关系的一种方式,以及如何将依赖关系簇分组在一起,但是在这里我并不真正了解该怎么做。

我可以将使用它们的ConverterService(s)分组,但是反正它们太多了。

让我知道是否需要其他详细信息。

2 个答案:

答案 0 :(得分:1)

我可以看到的问题是ProposalUpdateDefaultService做的事情太多,知道的太多。它接受很多服务,创建步骤并执行这些步骤,相反,它只应接受一个参数对象并进行更新,而不知道这些步骤是什么。

首先,我将尝试通过创建一个单独的包含服务和转换器的类来减少构造函数ProposalUpdateDefaultService中的参数。

public class ServicesAndConverters {
    ComplexService complexService;
    OtherComplexService otherComplexService

    //...

}

这样,代码可以更加简洁

public class ProposalUpdateDefaultService implements ProposalUpdateService {
    ServiceAndConverters serviceAndConvert;

    public ProposalUpdateDefaultService(final ServiceAndConverters serviceAndConverters) {
        this.serviceAndConvert = serviceAndConverters; //maybe group them in two different class??
    }

}

现在,我可以看到第二个问题是在ProposalUpdateDefaultService本身中创建步骤。这应该由不同阶层负责。像下面这样

 public class ProposalUpdateDefaultService implements ProposalUpdateService {
         ServiceAndConverters serviceAndConvert;
         StepCreator stepCreator = new StepCreator();

         public ProposalUpdateDefaultService(final ServiceAndConverters serviceAndConverters) {
             this.serviceAndConvert = serviceAndConverters;
             stepCreator.createSteps(this.serviceAndConverter);
         }

     }

StepCreator类应该看起来像这样

public class StepCreator implements ProposalUpdateService {
        private final ProposalStep<Proposal> stepOne;
        private final ProposalStep<Proposal> stepTwo;
        private final ProposalStep<ProposalTypeTwo> stepThree;
        private final ProposalStep<Proposal> stepFour;

        public void createSteps(ServiceAndConverters s) {
                // do the step processing here
        }

}

现在ProposalUpdateDefaultService可以执行这些步骤而无需知道什么步骤以及需要执行哪些服务

@Override
public void updateProposal(final ProposalTypeOne proposal) {
   stepCreator.getStepOne().process(proposal);
   stepCreator.getStepTwo().process(proposal);

   if (...) {
      stepCreator.getStepFour().process(proposal);
   }
}

答案 1 :(得分:1)

我发现更方便的解决方案是删除ProposalUpdateService抽象,并让EJB Bean管理各个步骤。

到目前为止,此抽象层是不必要的,并且每个步骤仍然可以单独使用。这两个ProposalUpdateService方法调用都成为EJB Bean中的私有方法。