最近在研读开源分布式定时任务框架elastic-job源码,基本清晰该框架逻辑架构和设计理念,现总结研读过程中使用到的设计模式。
1. 单例模式
设计模式中最基本也是最常用的一种,在es-job中使用如下:
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class JobRegistry {
private static volatile JobRegistry instance;
private Map<String, JobScheduleController> schedulerMap = new ConcurrentHashMap<>();
/**
* 获取作业注册表实例.
*
* @return 作业注册表实例
*/
public static JobRegistry getInstance() {
if (null == instance) {
synchronized (JobRegistry.class) {
if (null == instance) {
instance = new JobRegistry();
}
}
}
return instance;
}
该单例模式采用双重检查锁进行实现,需要注意静态实例用volatile关键字修饰是很有必要的,如果没有volatile则该单例模式可能出现多例的情况,原因如下:
volatile(java5):可以保证多线程下的可见性;
读volatile:每当子线程某一语句要用到volatile变量时,都会从主线程重新拷贝一份,这样就保证子线程的会跟主线程的一致。
写volatile: 每当子线程某一语句要写volatile变量时,都会在读完后同步到主线程去,这样就保证主线程的变量及时更新。
2. 工厂模式和模板模式
源码中用到的工厂模式是与模板模式一起使用的,
public static final class LiteJob implements Job {
@Setter
private ElasticJob elasticJob;
@Setter
private JobFacade jobFacade;
@Override
public void execute(final JobExecutionContext context) throws JobExecutionException {
JobExecutorFactory.getJobExecutor(elasticJob, jobFacade).execute();
}
}
public final class JobExecutorFactory {
/**
* 获取作业执行器.
*
* @param elasticJob 分布式弹性作业
* @param jobFacade 作业内部服务门面服务
* @return 作业执行器
*/
@SuppressWarnings("unchecked")
public static AbstractElasticJobExecutor getJobExecutor(final ElasticJob elasticJob, final JobFacade jobFacade) {
if (null == elasticJob) {
return new ScriptJobExecutor(jobFacade);
}
if (elasticJob instanceof SimpleJob) {
return new SimpleJobExecutor((SimpleJob) elasticJob, jobFacade);
}
if (elasticJob instanceof DataflowJob) {
return new DataflowJobExecutor((DataflowJob) elasticJob, jobFacade);
}
throw new JobConfigurationException("Cannot support job type '%s'", elasticJob.getClass().getCanonicalName());
}
}
此处使用的是简单工厂模式,通过不同参数生成不同 AbstractElasticJobExecutor 实例对象;
public abstract class AbstractElasticJobExecutor {
.......
/**
* 执行作业.
*/
public final void execute() {
process(.....);
}
protected abstract void process(ShardingContext shardingContext);
}
此处使用模板模式,使父类算法的具体实现延迟到子类,使子类不必改变一个算法的结构即可重定义该算法的步骤。
3. 策略模式
策略模式是比较常用的一种设计模式,其设计理念是:定义一系列算法,将它们一个个封装起来,并且使他们之间可以相互替换。
在es-job中的使用中是针对不同类型的任务类型设计不同的业务逻辑,其源码如下:
public interface JobTypeConfiguration {
/**
* 获取作业类型.
*
* @return 作业类型
*/
JobType getJobType();
/**
* 获取作业实现类名称.
*
* @return 作业实现类名称
*/
String getJobClass();
/**
* 获取作业核心配置.
*
* @return 作业核心配置
*/
JobCoreConfiguration getCoreConfig();
}
public final class SimpleJobConfiguration implements JobTypeConfiguration {
private final JobCoreConfiguration coreConfig;
private final JobType jobType = JobType.SIMPLE;
private final String jobClass;
}
public final class DataflowJobConfiguration implements JobTypeConfiguration {
private final JobCoreConfiguration coreConfig;
private final JobType jobType = JobType.DATAFLOW;
private final String jobClass;
private final boolean streamingProcess;
}
/**
* 创建Lite作业配置构建器.
*
* @param jobConfig 作业配置
* @return Lite作业配置构建器
*/
public static Builder newBuilder(final JobTypeConfiguration jobConfig) {
return new Builder(jobConfig);
}
通过传入不同的jobConfig对象实现不同类型的任务。
待续。。。