我是小蕉。
从前有座山,山里有座庙,庙里有个老和尚,阿不,有个餐厅的老板,在每天午餐之前,都要自己亲力亲为为各个小伙伴分配任务,大喊一声开饭啦,大家就屁颠屁颠跑过来领任务。炒菜嘛,就交给A来做,他的厨艺好。搬桌子嘛,交给B来做,他身强力壮。煮饭嘛,交给C来做,他比较细心。陪客人唠嗑嘛,就交给小蕉,毕竟他嘴皮子可厉害了。每天都这样,虽然很累,但老板倒也乐此不疲。直到有一天。
餐厅发展越来越好,员工越来越多,老板的员工达到了19876名,老板明显已经力不从心了,经常记错员工的名字,也经常记错要给员工安排的任务,又一次竟然把我当成隔壁老王,让我去扫厕所T_T。这也太委屈了,该怎么帮帮老板,顺便帮帮我自己呢?
在老板累死之前,我决定做一点事情,来解除这个死循环。
我们换一个思路,每个员工在入职的时候都会得到一份”工作要点“,然后老板快开饭的时候大喊一声,开饭啦。各个员工就观察老板的脸色,就各自行动去啦。A呢就自己去炒菜,搬桌子的事情就交给B啦,C自从没被派去扫地饭也煮得越来越好吃,一切都好起来了。
按照这样安排呢,这样后面就算新进一个员工,也只是多一发一份工作要点的事。
辟如一个员工太老了炒不了菜,给他换一份说明或者直接办理退休不处理事务就,在老板喊开饭的时候就直接忽略就好。就在机智的小蕉的建议下,老板进行了组织重整,终于闲下来了,又回到了整天唠嗑收钱的好日子了,我呢,也再也没有被派去扫厕所。
这!!!天哪!!!这跟今天要大家分享的,在实际工作中遇到的一个问题不谋而合啊!!!就是if else!!!看过一个多分支任务重跑类,就是由一个CODE来决定如何重跑。我的屏幕有24寸那么长,一屏幕看下来,满屏幕都是if else!!!What the。
if(some){}
else if(some else){
if(some){}
else{}
}
else if(some others){}
else if(some etc.){}...
看着这些代码这太难受了,后面也不好维护啊,这后面加一个功能岂不是要废?这么一大坨万一我还不敢轻易改,怕怕,怕怕。本着“我不管我就要改的”的善心,我决定重构一下这个代码。说走咱就走啊。天上的星星参北斗啊...
下面是纯技术干货,非技术宅的看官老爷可以直接左上角退出。
我们项目使用的是SpringMVC嘛,所以就大胆地使用Spring容器了。首先要有一个定时JOB吧,不然怎么来设计重跑,经验上来说,每五分钟跑一次,跑三次不成功,要么就是目标服务有问题,要么就是本地抛异常挂掉了。那就脑袋一拍,咱就使用观察者模式,让各个执使用Quartz来驱动这个定时任务好了。 定义一个bean然后类是下面这个,还有targetMethod属性要定义好就行了。
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
定义一个调度中心,也就是上面那玩意,用来管理整批的重跑任务。
@Service(ObserverCenter.SERVICE_ID)
class ObserverCenter{
public static final String SERVICE_ID="ObserverCenter";
//hold住所有的调度任务处理器,在下面会定义的
List registedObservers = new ArrayList();
//提供一个给处理器注册的接口
public void register(Observer observer){
this.registedObservers.add(observer);
}
//提供一个给处理器注销的接口
public void unRegister(Observer observer){
this.registedObservers.remove(observer);
}
//Quartz执行的方法
public void execute(){
//获得需要重跑的任务列表
List somethingNeedToRun = new ArrayList();
//将任务广播到所有的任务观察者中,由观察者决定是否处理以及如何处理
for(SomeRecords somethingNeedToRun in somethingNeedToRun){
for(Observer observer : registedObservers){
observer.handle(somethingNeedToRun);
}
}
}
}
好了,驱动类写完啦~谈谈观察类的子类把。首先会定义一个抽象类,作为所有调度任务的父类。每个观察者类都会注册到调度中心,所以预先实现好调度方法。@PostConstruct注解用于在实例构造完执行,这里用于把自己注册到调度中心。@PreDestory注解用于在实例销毁之前,这里用于把自己从调度中心注销。
public abstract class Observer(){
@Resource(name=ObserverCenter.SERVICE_ID)
private ObserverCenter observerCenter;
@PostConstruct
private registerToCenter(){
observerCenter.register(this);
}
@PreDestory
private unRegisterFromCenter(){
observerCenter.register(this);
}
void abstract handle(SomeRecords);
}
定义一个抽记录类。
public class SomeRecords{
}
每个继承了Observer的子类,在使用Spring的单实例模式,被容器构造完成后,都会自动注册到调度中心,在接受到来自调度中心的任务后,各个子类可以决定自己需不需要处理,以及怎么处理。接下来是一个驱动类的DEMO,
public class extends Observer(){
@Override
public void handle(SomeRecords){
Logger.log("I don't give a shit to the record!")
}
}
在这个设计模式下,不会有非常长的if else,可维护性大大提高。后续在增加一个调度子类,以及删除一个调度子类,都非常方便,不会影响任何其他的处理器。
好啦今天的分享就到这里,大家有什么建议可以在后台吐槽,反正我也不会回的,毕竟我懒。