【问题标题】: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 方法的信息 - 它是否在所有服务中执行相同类型的操作?

标签: java spring generics design-patterns


【解决方案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(..);
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-03-03
          • 2015-12-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多