英文:
removing duplicate code shared between sync and async implementations
问题
给定一个 Processor 接口:
public interface Processor {
PBResponse process(PBEntity pbEntity);
}
我在我的框架项目中有两个实现,一个是同步的:
@Service("Synchronous")
public class SyncProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
public SyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public PBResponse process(PBEntity pbEntity) {
pbRepository.save(pbEntity);
//其他业务逻辑和运行作业
jobRunner.runJob(pbEntity);
}
}
另一个是异步的:
public class AsyncProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
private ExecutorService executorService = Executors.newSingleThreadExecutor();
public AsyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public PBResponse process(PBEntity pbEntity) {
pbRepository.save(pbEntity);
executorService.execute(new PBJobRunTask(pbRepository, jobRunner, pbEntity));
return new PBResponse(...) //初始不完整的响应
}
private class PBJobRunTask implements Runnable {
private final PBSFeedRepository pbsFeedRepository;
private final JobRunner jobRunner;
private final PBEntity pbEntity;
public PBJobRunTask(PBRepository pbRepository, JobRunner jobRunner, PBEntity pbEntity) {
//初始化
}
@Override
public void run() {
//其他业务逻辑和运行作业
jobRunner.runJob(pbEntity);
}
}
}
在这两种同步和异步实现之间,请求的处理是相同的。唯一的区别是异步实现中使用了 ExecutorService 执行逻辑。
处理逻辑在同步和异步实现中的 Runnable 的 run() 方法中重复:
//重复的部分
pbRepository.save(pbEntity);
//其他业务逻辑和运行作业
jobRunner.runJob(pbEntity);
我需要一些帮助来去除这些重复的部分,使得这两个实现可以共享。我不确定是否将同步类注入到异步类中是否是一种良好的实践,因为它们都是 Processor 的实现。
什么是理想的,也是一个良好的模式,用于在这两个类之间共享业务逻辑。我们还有存在于两个实现中的存储库和 JobRunner,或许它们也可以被移动?
提前感谢您的帮助
英文:
Given that I have an Processor interface:
public interface Processor {
PBResponse process(PBEntity pbEntity);
}
And I have two implementation in my framework project, one synchronous:
@Service("Synchronous")
public class SyncProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
public SyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public PBResponse process(PBEntity pbEntity) {
pbRepository.save(pbEntity);
//other business logic and run job
jobRunner.runJob(pbEntity);
}
}
The Other Async:
public class AsyncProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
private ExecutorService executorService = Executors.newSingleThreadExecutor();
public SyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public PBResponse process(PBEntity pbEntity) {
pbRepository.save(pbEntity);
executorService.execute(new PBJobRunTask(pbRepository, jobRunner, pbEntity));
return new PBResponse(...) //initial incomplete Response
}
private class PBJobRunTask implements Runnable {
private final PBSFeedRepository pbsFeedRepository;
private final JobRunner jobRunner;
private final PBEntity pbEntity;
public PBJobRunTask(PBRepository pbRepository, JobRunner jobRunner, PBEntity pbEntity) {
//initialise
}
@Override
public void run() {
//other business logic and run job
jobRunner.runJob(pbEntity);
}
}
}
Processing of a request is identical between both sync and async implementations. The only difference is the logic is executed with an ExecutorService
with async implementation.
The processing logic is repeated in both Synchronous and Asynchronous implementations within the Runnable
run()
method:
//duplicated
pbRepository.save(pbEntity);
//other business logic and run job
jobRunner.runJob(pbEntity);
I need some help remove this duplicated where both these implementation can share. I am not sure whether inject Synchronous class into Async in a good practice as they are both implementations of Processor.
What would be ideal and a good pattern to share the business logic between two classes. We have the repository and JobRunner which also sits in both implementations and perhaps they can move also?
Thanks in advance
答案1
得分: 0
你可以使用模板方法模式。
定义一个抽象类AbstractProcessor
并将Processor
接口实现为final。在process(PBEntity pbEntity)
方法中,将步骤定义为受保护的方法,带有默认或无实现,在子类中覆盖特定步骤。
public abstract class AbstractProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
public AbstractProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public final PBResponse process(PBEntity pbEntity) {
someBusinessLogic(pbEntity);
execute(pbEntity);
return new PBResponse();
}
protected void someBusinessLogic(PBEntity pbEntity) {
pbRepository.save(pbEntity);
//some other business logic
}
protected void execute(PBEntity pbEntity) {
}
}
示例子类 -
@Service("Synchronous")
class SyncProcessor extends AbstractProcessor {
public SyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
super(pbRepository, jobRunner);
}
@Override
protected void execute(PBEntity pbEntity) {
getJobRunner().runJob(pbEntity);
}
}
英文:
You can use template method pattern.
Define abstract
class AbstractProcessor
and implement Processor
interface as final. In process(PBEntity pbEntity)
define steps as protected method with default/no implementation and in child class override specific step
public abstract class AbstractProcessor implements Processor {
private final PBRepository pbRepository;
private final JobRunner jobRunner;
public AbstractProcessor(PBRepository pbRepository, JobRunner jobRunner) {
this.pbRepository = pbRepository;
this.jobRunner = jobRunner;
}
@Override
public final PBResponse process(PBEntity pbEntity) {
someBusinessLogic(pbEntity);
execute(pbEntity);
return new PBResponse();
}
protected void someBusinessLogic(PBEntity pbEntity) {
pbRepository.save(pbEntity);
//some other business logic
}
protected void execute(PBEntity pbEntity) {
}
}
Example child class -
@Service("Synchronous")
class SyncProcessor extends AbstractProcessor {
public SyncProcessor(PBRepository pbRepository, JobRunner jobRunner) {
super(pbRepository,jobRunner);
}
@Override
public void execute(PBEntity pbEntity) {
getJobRunner().runJob(pbEntity);
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论