在使用相似对象的多个服务中重用相似方法的最佳方法是啥?

Posted

技术标签:

【中文标题】在使用相似对象的多个服务中重用相似方法的最佳方法是啥?【英文标题】:What is the best approach to reuse similar method in multiple Services that use similar objects?在使用相似对象的多个服务中重用相似方法的最佳方法是什么? 【发布时间】:2021-08-17 11:31:08 【问题描述】:

我有几个服务具有由调度程序调用的相同方法。这是一项服务的一个示例。

@Service
public class MyService1 

     @Autowired
     private MyLocalMapper1 localMapper1;
     
     @Autowired
     private MyLocalRepository1 localRepository1;

     @Autowired
     private MyExternalMapper1 externalMapper1;
     
     @Autowired
     private MyExternalRepository1 externalRepository1;
  

     public void startProcess() 
          //I use the mappers and the repositories in here
     

我有 15 个服务与这个服务完全相似,但每个服务都有一个特定的映射器(例如 MyLocalMapper2、MyLocalMapper3 等)以及存储库。

例如

 @Service
 public class MyService2 

     @Autowired
     private MyLocalMapper2 localMapper2;
     
     @Autowired
     private MyLocalRepository2 localRepository2;

     @Autowired
     private MyExternalMapper2 externalMapper2;
     
     @Autowired
     private MyExternalRepository2 externalRepository2;
  

     public void startProcess() 
          //I use the mappers and the repositories in here
     

考虑到它使用的对象在每个服务中都不同,是否有任何设计模式允许重用 startProcess 方法中的代码?

我想为每个对象创建接口,例如:LocalMapperInterface、LocalRepositoryInterface 等。并将所有这些接口作为参数传递给单个方法,但不确定这是否是最佳方法。

提前致谢。

【问题讨论】:

需要了解更多有关 startProcess 方法的信息 - 它是否在所有服务中执行相同类型的操作? 【参考方案1】:

我不确定,也许“模板方法模式”是一种可行的方法。

【讨论】:

【参考方案2】:

您可以创建一个如下所示的抽象类,并在所有 15 个服务中扩展它,前提是映射器和 repos 具有您可以在抽象类中使用的公共父类:

    public abstract class ScheduledService 
      public void startProcess() 
        LocalMapper localMapper = getLocalMapper();
        LocalRepository localRepo = getLocalRepository();
        ExternalMapper externalMapper = getExternalMapper();
        ExternalRepository externalRepo = getExternalRepository();
        // use above objects here!!
      

      public LocalMapper getLocalMapper();

      public LocalRepository getLocalRepository();

      public ExternalMapper getExternalMapper();

      public ExternalRepository getExternalRepository();
    

【讨论】:

【参考方案3】:

我会尝试在存储库和映射器中寻找常见的东西。因为如果存在差异,那么无论采用何种设计,都会导致违反 Liskov 的替代原则。 :(如果mapper的所有方法都可以拉成一个通用接口,那么就给所有的类传一个Mapper接口,它会自动变成一个Template方法:)

然后对存储库执行相同的操作,但如果其中任何一个 impl 不常见,则保持原样。

如果两个接口都可以提取,则寻找 startProcess 方法。如果只是因为映射器和存储库的组合不同而必须创建 100 个服务,并且必须使用不同数量的映射器和存储库,那么装饰器模式就是这种情况。但是,如果 startProcess 方法不常见,那么就保留它——因为那会被过度设计。

【讨论】:

【参考方案4】:
public abstract class MyService 
  @Autowired
  protected Mapper mapper;

  @Autowired
  protected Repository repository;

  //now becomes a Template method
  //if can't be turned into template method, then leave the method abstract instead
  public void startProcess() 
    ..
    something = mapper.map(..);
    ..
    repositoryResult = repository.doSomething(..);
  

【讨论】:

以上是关于在使用相似对象的多个服务中重用相似方法的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在非常相似的组件的情况下,进行条件渲染的最佳方法是啥?

Rails:分离两个非常相似的视图的最佳方法是啥?

基于关联计算表中行之间相似度的最佳方法是啥?

在给出相似输出神经网络的情况下,获得最佳匹配对的有效方法是什么?

怎么比较两个向量组相似度

比较对象数组,最佳方式