抽象类实现接口某个方法,再定义抽象方法(模版方法设计模式)
抽象类定义的抽象方法都是让子类实现的,也就是说扩展的抽象方法都在子类定制,共性的方法都可以在抽象类里面实现
例如下面这个例子,我们想在某个接口方法执行的时候 再执行某些自定义方法
就可以再抽象类里面实现这个接口方法,然后再定义几个抽象方法让子类去实现
public interface Job {
void execute(JobExecutionContext context)
throws JobExecutionException;
}
public abstract class AbstractJob implements Job {
public abstract void beforeExecuteJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
public abstract void afterExecuteJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
public abstract void executeJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
this.beforeExecuteJob(jobExecutionContext);
MasterSelector masterSelector = MasterSelector.getInstance();
if (masterSelector.isMaster()) {
masterSelector.increaseJobNum();
try {
long excuteTimeOut = jobExecutionContext.getJobDetail().getJobDataMap().getLong(Constants.TASK_EXCUETE_TIMEOUT_KEY);
Future<?> future = ExcuteTaskThreadPool.getThreadPoolExecutor().submit(new Thread(() -> {
try {
executeJob(jobExecutionContext);
} catch (JobExecutionException e) {
log.error("excute job error");
}
}));
future.get(excuteTimeOut, TimeUnit.MINUTES);
} catch (Exception e) {
log.error("excute job timeout", e);
//TODO 报警监控
} finally {
masterSelector.decreaseJobNum();
}
}
this.afterExecuteJob(jobExecutionContext);
}
}
抽象类+策略模式
父类定义的抽象方法子类都要实现,有时候某些方法不想子类实现,我们就可以使用抽象类+接口方式,
如果子类一旦有点多,都实现这个接口就没发做到代码重用, 这时候就可以使用策略模式
例如下面的flyable 就是变化的部分,我们把变化的部分抽象成接口
abstarct class Duck{
@Setter
Flyable flyable;
public void swim(){
//
}
public abstract void display();
public void performFly(){
flyable.fly();
}
}
public interface Flyable{
void flay();
}
public class FlyWithWing implements Flyable{
public void fly(){
//....
}
}
public class GreenDuck extends Duck{
public GreenDuck(){
this.flyable=new FlyWithWing();
}
@Override
public void display(){
}
}
double check
private final Map<String, String> myCache = new ConcurrentHashMap<String, String>(256);
public String getValue(String name) {
String value = myCache.get(name);
//check one
if (value == null) {
synchronized (this.myCache) {
value = myCache.get(name);
//check two
if (value == null) {
value = getValueFromDB();
}
myCache.put(value, value);
}
}
return value;
}
public String getValueFromDB() {
return new Random().nextInt(100) + "";
}
// booolean 类型double check
private volatile boolean isInitialized = false;
if (!isInitialized) {
synchronized (Object.class) {
if (!isInitialized) {
//....
isInitialized=true;
}
去锁cas-boolean
private static AtomicBoolean flag = new AtomicBoolean();
public void test(){
if (flag.compareAndSet(false, true)) {
///
}else{
////
}
}
去锁-future
假如有这样一个业务场景,从数据库里面查询某个key的值,并将查询到的值缓存到本地。
如果并发的去查询某个key的值,怎么保证只会调用一次数据库。
//有锁版本-上面的double check
protected String getWithLock(String key, String defaultValue) {
ConfigValue configValue = readCache(key);
if (configValue == null) {
synchronized (object) {
configValue = readCache(key);
if (configValue == null) {
configValue = get(key);
writeCache(key, configValue);
}
}
}
return configValue.getValue() == null ? defaultValue : configValue.getValue();
}
//无锁版本
private ConcurrentMap<String, ConfigFuture> configFutures = new ConcurrentHashMap<String, ConfigFuture>();
protected String get(String key, String defaultValue) {
//读
ConfigValue configValue = readCache(key);
if (configValue == null) {
ConfigFuture existingFuture = null;
//无锁版本1
ConfigFuture future = new ConfigFuture(key);
//putIfAbsent可以巧妙避免同时生成多个future
existingFuture = configFutures.putIfAbsent(key, future);
if (existingFuture != null) {
log.info("wait future");
// wait for other threads to load the config
try {
configValue = existingFuture.get();
} catch (Exception e) {
}
} else {
// load the config and notify other threads
try {
configValue = get(key);
future.setResult(configValue);
writeCache(key, configValue);
} catch (Exception e) {
future.setResult(e);
} finally {
configFutures.remove(key);
}
}
//无锁版本2 多次穿透数据库,多线程可能会生成多个,new ConfigFuture
/*ConfigFuture future2 = configFutures.get(key);
if(future2==null){
future2 = configFutures.get(key);
if(future2==null){
log.info("future2 is null");
configFutures.put(key, new ConfigFuture(key));
configValue = get(key);
writeCache(key, configValue);
}
//dd
}else{
try {
configValue = future2.get();
} catch (Exception e) {
}
}*/
}
//自定义future
public class ConfigFuture implements Future<ConfigValue> {
private String key;
private CountDownLatch latch;
private Object result;
public ConfigFuture(String key) {
this.key = key;
latch = new CountDownLatch(1);
}
@Override
public boolean cancel(boolean arg0) {
return false;
}
@Override
public ConfigValue get() throws InterruptedException, ExecutionException {
latch.await();
if (result instanceof Throwable) {
throw new ExecutionException((Throwable) result);
}
return (ConfigValue) result;
}
@Override
public ConfigValue get(long arg0, TimeUnit arg1)
throws InterruptedException, ExecutionException, TimeoutException {
latch.await(arg0, arg1);
if (result instanceof Throwable) {
throw new ExecutionException((Throwable) result);
}
return (ConfigValue) result;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return result != null;
}
public void setResult(Object result) {
this.result = result;
latch.countDown();
}
}
tempate
public class RedisDaoTemplate {
@Autowired
private RedisPool redisPool;
public <T> T execute(RedisCallback<T> rc) throws Exception {
Jedis jedis = null;
List<Object> object = null;
try {
// 用默认的db 0;
jedis = redisPool.getJedis();
return rc.doInRedis(jedis);
}
finally {
redisPool.returnJedis(jedis);
}
}
}
public interface RedisCallback<T> {
T doInRedis(Jedis jedis) throws Exception;
}
一些常用命名方式
xxProvider ( 定义了建立,配置,得到,管理和控制0个或多个对象Manager,一个应用在运行时可能访问0个或者多个)
例如:CachingProvider、ConfigProvider
xxManager(对象管理器)
例如: CachingManager、ConfigManager
xxListener(监听器,当有变动当时候,会通知)
例如:
ConfigChangeListener
public interface ConfigChangeListener {
void onKeyUpdated(String key, String value);
void onKeyAdded(String key, String value);
void onKeyRemoved(String key);
}
NodeCacheListener:
public interface NodeCacheListener{
/**
* Called when a change has occurred
*/
public void nodeChanged() throws Exception;
}