关于设计的个人看法
我们设计一个功能的时候,要考虑的无非是那些问题:可靠性,鲁棒性,解耦性,扩展性,可读性等等。
我们对代码和功能的设计过程,从面相对象的角度来讲就是一个拟物或者拟人化的一个过程——我们先确定某个功能需要什么样的角色或者“零部件”参与,然后创建对应的类,指定类的角色职能;然后各个类各司其职;然后再考虑类的扩展性相关的问题,做出优化。
设计功能的第一步当然是明确需求,但是功能落地的重要过程我认为就是拟物拟人化的这个过程。
设计案例分析
现在我们有个需求,异步模块——将要执行的数据放到后台异步去执行,使用场景有数据导入导出,数据库间数据同步等。
现在我们进行拟物拟人化的过程(角色划分)我将这个功能划分成一下几个角色
- 任务 指要处理的数据等
- 资源 这里单指线程池
- 任务处理器 处理任务的具体逻辑。
- 管理器 负责调度线程,安排任务,将任务分发给各个处理器
功能设计到这,这个框架只能满足使用要求,通用性不强;就是说,能用但是比较垃圾。为什么这么说,
首先,我们任务应该以什么样的形式获取?又以什么样的形式去发布一个一个任务?框架中未做说明,也没有角色来干这个事情,所以我们要在管理器中定义一个命令模式,这个命令就是任务,命令方法就是发布任务,再在其内部使用模板方法模式固定一些算法。再添加一个任务工厂来获取和管理任务。
然后任务处理器这一端,任务处理逻辑肯定是使用者自己实现的,因此要具有适配性,这个适配性的支持,可以通过接口也可以通过注解,这都无所谓,所以我们还要添加一个任务处理器适配器。
最后框架就成了这个样子:
- 任务(命令)
- 任务工厂
- 任务处理器
- 任务处理器适配器
- 管理器
- 资源(线程池)
OK,实话告诉你吧,这个框架和 springmvc
的原理是一个意思:request 对应任务、 dispatchServlet对应的是管理者,Maphandler 对应的是处理器适配器,controller对应任务处理器, 任务工厂充当一个前端用户角色发送一个个请求。我这里多了个命令发送方的角色让管理器充当了,你也可以在添加一个命令发送器类。这个异步框架流程就如下:
- 调用命令发送器发送一个命令(任务); 命令发送器根据具体实现来决定这个命令是应该放入到内存中还是放入到数据库里还是直接执行。
- 任务工厂从数据库,或者内存或者别的什么地方读取出任务,排根据任务优先级序任务,然后将任务交给管理器。
- 管理器根据任务类型匹配到对应的任务处理器,交给任务处理器去处理
任务处理器的实现就像springmvc那样,我们可以定义一个处理器接口,然后所有实现该接口的并注入到spring容器的对象都是处理器。也可以定义一个像@requestMaoing
那样的注解,所有加上该注解的方法都会被适配成一个处理,实现起来也很容易。为了方便使用,我们还可以再对任务加一个监听器,我们想发布任务的时候只要抛出一个事件即可,当然这只是附带功能,非必须的功能。
关于代码可读性的思考
一个好的设计模式还好说,一个使用糟糕的设计模式简直是灾难,作者就经历过这种灾难:设计模式用的莫名其妙,不暗2套路来,命名也无迹可寻,这样的代码可读性就很差。因为设计模式之间类关系本身就很复杂,在少一点注释,真的很难去读懂。那么我们要怎么让一段代码能让别人读懂呢?第一就是加注释,第二就是命名规范。下面我们就来说说设计模式的命名规范吧。
基本的一些命名:
- 模板方法模式的类一般以
template
结尾 - 工厂模式一般以
factory
结尾 - 代理模式一般以
proxy
结尾,代理方法一般命名为invoke()
- 执行命令的方法一般叫
execute()
,命令类一般以Command
结尾 - 观察者模式中,监听器一般以
listener
结尾 - 建造者一般以
builder
结尾 - 适配器
Adapter
结尾
一些常用的“拟物” 结尾名词
-
处理器/执行器
Resolver Processor Handler Executor Performer Runner
-
管理器控制器
Controller Manager Ordinator Leader Master
-
转换器
Encoder/Decoder Transformer Converter
- 映射器
Mapper/Mapping
- 选择器
Chooser
Selector
小结
对于许多源码而言,设计模式都是杂糅在一起的,许多类你不能片面的划为哪一个设计模式,它可能在许多模式里面都充当着角色。我们阅读源码的时候要有通过命名去猜设计模式能力;同时我们也要有一定的联想能力,能够在实战中联想到相关源码,要学会 “抄作业” 。