抽象类中的属性和子类的属性

发布时间 2023-08-24 16:05:36作者: 做时间的好朋友

抽象类中的属性和子类的属性

1.场景说明

  1. 抽象类用做父类
  2. 子类继承抽象类
  3. 抽象类中定义好公共方法,方法里调用差异内容。每个子类中实现其中自己差异的逻辑就好

2.两种思路

  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 说明

  1. 定义3个抽象方法,prepare,run,after
  2. 子类实现prepare,run,after这3个方法
  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 代码说明

  1. 抽象类中定义了属性queryConditions
  2. 并且定义了一个带参数queryConditions的构造函数,子类通过构造函数把属性定义进来
  3. 子类通过定义无参的构造函数,然后调用super(queryConditions)把属性字段赋值传递进去
  4. 抽象类中直接定义好方法build,里面调用了queryConditions属性字段,实现业务逻辑,具体queryConditions的差异性,每个子类中自己去区分