设计模式 之 模板方法
模板方法设计模式的定义:在操作中定义算法的框架,将某些步骤推迟到子类。模板方法允许子类重新定义算法的某些步骤,而不更改算法的结构。说人话,我的理解是,子类的父级抽象类完成行为的实现,同时将各子类差异性的一小部分实现交给子类完成。下面是我在项目中实际用到的一段程序,一开始就这样写了,却不知道这种写法就是模板方法的设计模式,也是呵呵呵了。
package com.*.base.kafka.message;
import com.*.base.MyExecutor;
import com.*.common.tools.jedis.RedisUtil;
import com.*.common.utils.DateUtil;
import com.*.common.utils.StringUtil;
import com.*.service.extend.ReqLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.TimeUnit;
@Slf4j
public abstract class BaseConsumer {
@Autowired
ReqLogService reqLogService;
@Autowired
MyExecutor myExecutor;
public void receive(ConsumerRecord<String, String> record) {
myExecutor.execute(()->{
log.info("消息接收 topic:{} key:{} message:{}", record.topic(), record.key(), record.value());
String key = record.key();
if (StringUtil.isBlank(key)){
log.info("消息队列未设置key值");
} else {
if (RedisUtil.setNX(key, key)) {
RedisUtil.expire(key, RedisUtil.TEN_MINUTE);
try {
this.handle(record);
} catch (Exception e){
reqLogService.save(record.topic(), record.key(), record.value(), e);
log.error(e.getMessage, e);
} finally {
// RedisUtil.del(key); 消息过快消费掉后删除key时无法防止重复消费
}
} else {
log.info("已被其它服务消费 topic:{} key:{}", record.topic(), record.key());
}
}
});
}
public abstract void handle(ConsumerRecord<String, String> record);
}
总结
子类的公共方法实现适合放置在父类中,但这个公共方法实现又并非完全一致,还是有些差异化的功能需要子类自身去完成,所以父类中必然存在一个抽象的方法交给子类实现,因此父类也必然是一个抽象类。
子类也可以是抽象类,这取决于具体业务的封装层次,核心思想是通过抽象的办法提高代码的复用能力。