当前位置: 首页 > 后端技术 > Java

面试的时候不要说你不会设计模式

时间:2023-04-01 20:33:26 Java

前言最近在设计一个中间件的测试方案。这个测试计划需要包含不同的测试逻辑,但相同的是每个环节都需要记录;例如,统计耗时和调用通知API的逻辑是一样的。如果每个测试都单独写这些逻辑,无疑会做很多重复性的工作。基于以上特点,很容易将模板方法想象成一种设计模式。这是一种上层定义框架,下层提供不同实现的设计模式。比如在装修房子的时候,业主可以根据自己的喜好来装饰不同的房间,但是不能修改整体的平面图。例如,不得建造承重墙。而这些固定的规章制度是上层框架给的约束,下层的不同实现则由业主自己决定;因此,为整栋建筑固定了框架,让业主可以在有限的范围内自由发挥,方便物业的管理。管理。具体实现以我的案例背景为例。首先需要定义上层框架:JavaEventinterface:publicinterfaceEvent{/***添加新任务*/voidaddJob();/***已执行单个任务**@paramjobName任务名称*@paramfinishCost任务完成时间*/voidfinishOne(StringjobName,StringfinishCost);/**单任务执行异常*@paramjobDefinetask*@parame异常*/voidoneException(AbstractJobDefinejobDefine,Exceptione);/***所有任务完成*/voidfinishAll();}publicvoidstart(){event.addJob();try{CompletableFuture.runAsync(()->{StopWatchwatch=newStopWatch();try{watch.start(jobName);//不同的子服务实现run(client);}catch(Exceptione){event.oneException(this,e);}最后{watch.stop();event.finishOne(jobName,StrUtil.format("cost:{}s",watch.getTotalTimeSeconds()));}},TestCase.EXECUTOR).get(超时,TimeUnit.SECONDS);}catch(Exceptione){event.oneException(this,e);}}/**运行繁忙的代码*@paramclient*@throwsExceptione*/publicabstractvoidrun(Clientclient)throwsException;其中核心是run函数,是一个抽象函数,具体实现交给子类;互不干扰,整体流程完全一样:记录任务数,统计耗时异常记录等流程接下来我们看看如何使用:AbstractJobDefinejob1=newTest1(event,"Test1",client,10);CompletableFuturec1=CompletableFuture.runAsync(job1::start,EXECUTOR);AbstractJobDefinejob2=newTest2(event,"Test2",client,10);CompletableFuturec2=CompletableFuture.runAsync(job2::start,EXECUTOR);AbstractJobDefinejob3=newTest3(event,"Test3",client,20);CompletableFuturec3=CompletableFuture.runAsync(job3::start,EXECUTOR);CompletableFutureall=CompletableFuture.allOf(c1,c2,c3);all.whenComplete((___,__)->{event.finishAll();client.close();}).get();显然,Test1~3都继承了AbstractJobDefine,并在其中实现了run函数。使用时,只需要创建不同的实例,等待它们完成即可。之前Java有不同的应用:https://crossoverjie.top/2019/03/01/algorithm/consistent-hash/?highlight=%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95#%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95Go同样的例子也可以用Go实现:funcTestJobDefine_start(t*testing.T){event:=NewEvent()j1:=&JobDefine{Event:event,Run:&run1{},JobName:"job1",Param1:"p1",Param2:"p2",}j2:=&JobDefine{事件:event,运行:&run2{},JobName:"job2",Param1:"p11",Param2:"p22",}j1.Start()j2.Start()for_,ch:=rangeevent.GetChan(){<-ch}log.Println("finishall")}func(r*run2)Run(param1,param2string)error{log.Printf("run3param1:%s,param2:%s",param1,param2)时间。Sleep(time.Second*3)returnerrors.New("testerr")}func(r*run1)Run(param1,param2string)error{log.Printf("run1param1:%s,param2:%s",param1,param2)returnnil}使用也和Java类似,创建不同的实例;最后,等待所有任务执行完毕,总结设计模式往往是对某些通用能力的抽象,但没有一种设计模式可以适用于所有场景;不同的需求需要选择不同的设计模式。至于如何在工作中做出正确的选择,需要自己每天的积累;比如想更多地了解不同设计模式的场景,或者阅读更多优秀的代码,Java中的InputStream/Reader/Writer等IO相关类都有具体的应用。