简体   繁体   English

Spring 引导服务中的流畅接口

[英]Fluent Interface in Spring Boot Service

I am building a Spring Boot project for work.我正在为工作构建一个 Spring 引导项目。 In this project I have service which is tasked with getting certain Documents from another backend.在这个项目中,我的服务任务是从另一个后端获取某些文档。 There a quite a lot of different scenarios where the documents have to meet certain criteria eg be from a certain date, which can be matched freely.有很多不同的场景,其中文档必须满足某些标准,例如来自某个日期,可以自由匹配。 Currently this is accomplished with normal method like so:目前这是通过正常方法完成的,如下所示:


@Service
public class DocumentService(){

  private OtherService otherService;

  @Autowire
  public DocumentService(OtherService otherService){
    this.otherService = otherService;
  }

  public List<Document> getDocuments() {
   ...
  }

  public List<Document> getDocuments(LocalDate date) {
   ...
  }

  public List<Document> getDocuments(String name){
   ...
  }

  public List<Document> getDocuments(String name, LocalDate date){
   ...
  }

}

I find this to be a rather bad solution because for every new combination there would need to be a new method.我发现这是一个相当糟糕的解决方案,因为对于每个新组合都需要一种新方法。 For that reason I'd like to use a fluent style interface for that, something like this:出于这个原因,我想为此使用流畅的样式界面,如下所示:

//Some other class that uses DocumentService
documentService().getDocuments().withDate(LocalDate date).withName(String name).get();

I'm familiar with the Builder Pattern and method chaining but I don't see a way how I can adapt either one of those.我熟悉 构建器模式方法链,但我看不到如何适应其中任何一个。 Seeing as, per my understanding, @Service-classes are singletons in Spring Boot.据我了解,@Service-classes 是 Spring Boot 中的单例。

Is this at all possible with Spring Boot? Spring 引导是否有可能?

If you want to use a fluent interface here, the object returned by your getDocuments() method would have to be the starting point for the method chain.如果您想在此处使用流畅的接口,您的getDocuments()方法返回的 object 必须是方法链的起点。 Perhaps create something like a DocumentFilter class that you can return from there, then you'll end up with something like this:也许创建一个类似DocumentFilter class 的东西,你可以从那里返回,然后你会得到这样的东西:

documentService.documents().getDocuments().withDate(LocalDate date).withName(String name).getDocuments()

In this example, your DocumentFilter will have withDate(...) and withName(...) methods, and each subsequent call includes all of the criteria from the preceding DocumentFilter .在此示例中,您的DocumentFilter将具有withDate(...)withName(...)方法,并且每个后续调用都包含来自前面DocumentFilter的所有条件。

Doesn't have to be a Spring Boot solution, why not just introduce a POJO builder-like local class:不一定非得是 Spring 引导解决方案,何不直接引入类似 POJO builder 的本地 class:

@Service
public class DocumentService(){
    public Builder documents() {
        return new Builder();
    }

    public class Builder {
        private LocalDate date;
        private String name;

        public Builder withDate(LocalDate date) {
            this.date = date;
            return this;
        }

        // etc

        public List<String> get() {
            final List<SomeDTO> results = otherService.doQuery(name, date, ...);
            // TODO - tranform DTO to List<String>
            return list;
        }
    }
}

Obviously make it static if it doesn't need access to the parent component.如果不需要访问父组件,显然将其设为 static。

You could make the Spring component and the builder be the same object but that does feel contrived, also I expect you would like to be able to support multiple builders.可以使 Spring 组件和构建器是相同的 object 但这确实让人觉得做作,而且我希望您能够支持多个构建器。

Also I'm assuming the parent component is genuinely a service, ie it doesn't contain any state or mutators, otherwise you are introducing potential synchronization problems.另外我假设父组件是真正的服务,即它不包含任何 state 或突变体,否则您将引入潜在的同步问题。

EDIT: Just for illustration the builder maintains the arguments to be passed to the otherService and performs any service-like transforms.编辑:只是为了说明,构建器维护 arguments 以传递给otherService并执行任何类似服务的转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM