抽象类中的属性和子类的属性
抽象类中的属性和子类的属性
1.场景说明
- 抽象类用做父类
- 子类继承抽象类
- 抽象类中定义好公共方法,方法里调用差异内容。每个子类中实现其中自己差异的逻辑就好
2.两种思路
- 抽象类中定义抽象方法,子类实现抽象方法
- 抽象类中定义属性,每个子类中对该属性的值进行定义
3.思路1的代码逻辑
抽象类
@Data
@Slf4j
public abstract class AbstractNotifyProcessor<T extends NotificationContext> implements NotifyProcessor<T> {
private Retryer<Boolean> retry = RetryerBuilder.<Boolean>newBuilder()
.retryIfResult(Predicates.isNull())
.retryIfResult(Predicates.equalTo(false))
.retryIfExceptionOfType(IOException.class)
.retryIfExceptionOfType(SocketTimeoutException.class)
.retryIfExceptionOfType(ConnectException.class)
.withWaitStrategy(WaitStrategies.fixedWait(3, TimeUnit.SECONDS))
.retryIfRuntimeException().withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
abstract void prepare(T t);
abstract void run(T t) throws Exception;
abstract void after(T t);
abstract ThreadPoolExecutor getExecutor();
abstract String getMethodKey();
@Override
public final void process(T t) {
getExecutor().submit(() -> {
CallerInfo info = null;
try {
info = Profiler.registerInfo(getMethodKey());
prepare(t);
run(t);
} catch (Exception e) {
Profiler.functionError(info);
log.error("消息ID:[{}] executor process msg err: ", t.messageId, e);
t.notificationResult.setSuccess(false);
t.notificationResult.setException(e.toString());
} finally {
Profiler.registerInfoEnd(info);
after(t);
}
});
}
}
子类
@Slf4j
public class EmailNotifyProcessor extends AbstractNotifyProcessor<NotificationContext> {
public static final String MONITOR_KEY = "delta.notify.email.process.method";
private ThreadPoolExecutor notifyExecutor;
public EmailNotifyProcessor() {
this.notifyExecutor = ThreadUtils.newDaemonFixedThreadPool(20,"EmailNotifyThread");;
}
@Override
void prepare(NotificationContext context) {
}
@Override
void run(NotificationContext context) throws Exception {
}
@Override
void after(NotificationContext context) {
}
@Override
ThreadPoolExecutor getExecutor() {
return notifyExecutor;
}
@Override
String getMethodKey() {
return MONITOR_KEY;
}
}
3.1 说明
- 定义3个抽象方法,prepare,run,after
- 子类实现prepare,run,after这3个方法
- 父类抽象类中定义final修饰的主方法,主方法里再调用prepare,run,after抽象方法,就调用了子类的方法
4.思路2的代码逻辑
抽象类
@Slf4j
public abstract class AbstractSlowLogSearchRequestBuilder implements SearchRequestBuilder<QuerySlowLogRecordParam, SearchSourceBuilder> {
// 定义变量
private Map<Predicate<QuerySlowLogRecordParam>, BiConsumer<BoolQueryBuilder,QuerySlowLogRecordParam>> queryConditions;
// 定义带参数的构造方法,子类需要通过这个构造方法进行属性字段的赋值
public AbstractSlowLogSearchRequestBuilder(Map<Predicate<QuerySlowLogRecordParam>, BiConsumer<BoolQueryBuilder, QuerySlowLogRecordParam>> queryConditions) {
this.queryConditions = queryConditions;
}
@Override
public SearchSourceBuilder build(QuerySlowLogRecordParam param) {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
queryConditions.forEach((condition, action) -> {
if (condition.test(param)){
action.accept(boolQueryBuilder,param);
}
});
boolQueryBuilder.must(QueryBuilders.rangeQuery("time").from(param.getAlarmFrom()).to(param.getAlarmTo()));
boolQueryBuilder.must(QueryBuilders.termQuery("slowLogType", param.getLogType().name()));
searchSourceBuilder.query(boolQueryBuilder);
searchSourceBuilder.sort("time", SortOrder.DESC);
return searchSourceBuilder;
}
}
子类
@Slf4j
class EsSlowLogSearchRequestBuilder extends AbstractSlowLogSearchRequestBuilder {
public EsSlowLogSearchRequestBuilder(){
super(MapUtil.builder(new LinkedHashMap<Predicate<QuerySlowLogRecordParam>, BiConsumer<BoolQueryBuilder,QuerySlowLogRecordParam>>())
.put(param -> CollectionUtil.isNotEmpty(param.getResourceIds()), (boolQueryBuilder, param) -> boolQueryBuilder.must(QueryBuilders.termsQuery("resourceId", param.getResourceIds())))
.put(param -> Objects.isNull(param.getAlarmFrom()) || Objects.isNull(param.getAlarmTo()), (boolQueryBuilder, param) -> {
Long to = System.currentTimeMillis();
Long from = to - 15 * 60 * 1000;
param.setAlarmFrom(from);
param.setAlarmTo(to);
})
.put(param -> !Objects.isNull(param.getQueryId()), (boolQueryBuilder, param) -> boolQueryBuilder.must(QueryBuilders.termQuery("id", param.getQueryId())))
.build());
}
}
4.1 代码说明
- 抽象类中定义了属性queryConditions
- 并且定义了一个带参数queryConditions的构造函数,子类通过构造函数把属性定义进来
- 子类通过定义无参的构造函数,然后调用super(queryConditions)把属性字段赋值传递进去
- 抽象类中直接定义好方法build,里面调用了queryConditions属性字段,实现业务逻辑,具体queryConditions的差异性,每个子类中自己去区分
原创:做时间的朋友