首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在春天用自动毛豆创建一个简单的工厂模式?

如何在春天用自动毛豆创建一个简单的工厂模式?
EN

Stack Overflow用户
提问于 2019-01-10 17:50:56
回答 1查看 9.6K关注 0票数 9

我有一个带有4种非常相似方法的控制器,在远程服务器上调用API来对不同类型的用户执行不同的操作。在这些API调用之间更改的只是端点和一些参数。

因此,这4种方法都用非常相似的代码调用服务:它们从服务器获得一个令牌,设置参数,返回API的响应。由于稍后将添加更多操作,我决定使用使用Factory方法模式创建ServiceFactory,并在服务上使用模板模式以避免代码重复。

我的问题是,为了让工厂自动更新服务,它需要耦合到它们,我必须对每个实现进行@Autowire。有没有更好的解决办法?

下面是我到目前为止掌握的代码:

休息控制器

代码语言:javascript
复制
@RestController
public class ActionController {
  @Autowired
  private SsoService ssoService;

  // this is the factory
  @Autowired
  private ServiceFactory factory;

  @PostMapping("/action")
  public MyResponse performAction(@RequestBody MyRequest request, HttpServletRequest req) {
    // template code (error treatment not included)
    request.setOperator(ssoService.getOperator(req));
    request.setDate(LocalDateTime.now());
    return serviceFactory.getService(request).do();
  }
}

服务厂

代码语言:javascript
复制
@Component
public class ServiceFactory {

  @Autowired private ActivateUserService activateUserService;
  @Autowired private Action2UserType2Service anotherService;
  //etc

  public MyService getService(request) {
    if (Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType()) {
      return activateUserService;
    }
    // etc
    return anotherService;
  }
}

服务基础,实现MyService接口

代码语言:javascript
复制
public abstract class ServiceBase implements MyService {

  @Autowired private ApiService apiService;
  @Autowired private ActionRepository actionRepository;
  @Value("${api.path}") private String path;

  @Override
  public MyResponse do(MyRequest request) {
    String url = path + getEndpoint();
    String token = apiService.getToken();

    Map<String, String> params = getParams(request);
    // adds the common params to the hashmap

    HttpResult result = apiService.post(url, params); 
    if (result.getStatusCode() == 200) {
      // saves the performed action
      actionRepository.save(getAction());
    }
    // extracts the response from the HttpResult
    return response;
  }
}

服务实现(有4)

代码语言:javascript
复制
@Service
public class ActivateUserService extends ServiceBase {
  @Value("${api.user.activate}")
  private String endpoint;

  @Override
  public String getEndpoint() {
    return endpoint;
  }

  @Override
  public Map<String,String> getParams(MyRequest request) {
    Map<String, String> params = new HashMap<>();
    // adds custom params
    return params;
  }

  @Override
  public Action getAction() {
    return new Action().type(ActionType.ACTIVATED).userType(UserType.USER);
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-10 18:09:19

您可以@Autowired一个List of MyService,它将创建实现MyService接口的所有bean的List。然后,您可以向MyService添加一个方法,该方法接受一个MyRequest对象,并决定它是否能够处理该请求。然后,可以对List of MyService进行筛选,以找到第一个能够处理请求的MyService对象。

例如:

代码语言:javascript
复制
public interface MyService {

    public boolean canHandle(MyRequest request);

    // ...existing methods...
}

@Service
public class ActivateUserService extends ServiceBase {

    @Override
    public boolean canHandle(MyRequest request) {
        return Action.ACTIVATE.equals(request.getAction()) && UserType.USER.equals(request.getUserType());
    }

    // ...existing methods...
}

@Component
public class ServiceFactory {

    @Autowired
    private List<MyService> myServices;

    public Optional<MyService> getService(MyRequest request) {
        return myServices.stream()
            .filter(service -> service.canHandle(request))
            .findFirst();
    }
}

注意,上面的ServiceFactory实现使用了8+。如果无法使用Java 8或更高版本,则可以通过以下方式实现ServiceFactory类:

代码语言:javascript
复制
@Component
public class ServiceFactory {

    @Autowired
    private List<MyService> myServices;

    public Optional<MyService> getService(MyRequest request) {

        for (MyService service: myServices) {
            if (service.canHandle(request)) {
                return Optional.of(service);
            }
        }

        return Optional.empty();
}

有关将@AutowiredList结合使用的更多信息,请参见Autowire reference beans into list by type

该解决方案的核心是将决定MyService实现是否可以处理MyRequest的逻辑从ServiceFactory (外部客户端)转移到MyService实现本身。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54134333

复制
相关文章

相似问题

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