您的位置:首页 > 其它

项目问题思考之策略模式

2015-10-03 22:42 405 查看
求:
项目中一个模块需要支持对图片,PDF,文本文件的操作,需要读取他们的内容在前台显示,显示缩略图,保存他们的内容到后台,删除内容等


问题与教训:
最初安排我任务时说只需要支持图片跟pdf就可以了,然后我觉得很简单,于是不加思索的开始做了,没有考虑以后会不会添加新的文件类型等等,作为一个软件开发人员应该考虑的可拓展性.
最终工作很“顺利的完成了”,我是这样实现的,我定义了一个SpringController,处理前台传来的数据,或者为前台提供交互,然后在这个controller中使用if,else语句判断文件类型然后做了相应处理,代码有杂又乱但没有多做考虑.
问题来了,突然一天领导告诉我添加对文本本件,XML文件的支持,好吗,然后我就开始加,越加越杂乱,越加越郁闷,虽然不难,但是这样下去不是办法,以后再加其他类型的支持怎么办,那岂不是要代码爆炸了。当然可能你会想每个ifelse中的代码都抽取到一个一个独立的方法或者类中去,可是那么多的ifelse总会让人感觉你的不专业。


解决思路:
后来我想了想,决定重构这块代码,大致的问题就是这几点:
1,我们希望这个controller能够动态的分发请求到对应的处理方法中去,即如果用户请求图片得内容,或者缩略图,controller能识别并正确调用处理逻辑
2,我们希望能够在新的需求(新的类型)到来时不需要改写现有的代码,只需将新的处理逻辑类编译好后上传到服务器即可实现新类型的支持(因为如果程序已部署到远程服务器上,你还需要修改代码,再编译在重启服务器那是相当糟糕的体验)
3,我们需要一种方式来告知代码或者说注册新的处理器
当能解决了以上三个问题后,当新的需求到来时,我想我们就可以从容的处理了,因为我们只需编写相应的处理逻辑并注册给controller即可。其他什么都不需要做,是不是很爽呢?


解决方案:
考虑好以上三个问题,我便想到了JDBC,因为jdbc只是为我们提供了接口,对于接口使用者(我们)其中的实现都是隐藏的,因为无论你使用oracle,sqlserver还是mysql,代码都是一样的,你只需要注册相应驱动即可了。这个问题跟我们遇到的问题及其的相似,因为如果有新的数据库供应商想要提供java的支持,同样只需要实现jdbc的接口即可。
所以首当其中,我们需要抽象当前的问题,图片,pdf,文本等都是一种资源Resource,而他们都需要这样几个操作因此我们可以定义一个接口





这个接口类似于JDBC中的Connection,定义了对资源的操作接口,这样当需要新的类型需要添加时只需要实现该接口,并注册,那应该如何注册呢?注册到哪里呢?因此我们需要一个类来管理ResourceHandler





这个ResourceHandlerManager只要两个方法获取具体的handler,注册新的handler。因此在SpringHandler只需调用resourceHandlerManager.getHandler(handlerName);即可了,那这个handlerName是什么呢?这个就需要我们通过一种方式来注册到Manager中了,这里我们可以使用反射,将所有的handler实现类写到一个配置文件中类似于这个





这样我们只需在服务器启动时或者周期性的读取改配置文件,并注册到manager中即可了,如果有新的类型添加只需在配置文件中加入对应的类全名即可了,而不需要重新编译。到了这里我们看看是不是满足了以上三个需求呢?


1、controller正确分派请求,这个其实很简单,我们只需维护一个文件后缀到handler名称的Map即可了,请求到来时获取文件后缀名,然后查找映射获取handler名称即可成功分配了 

2、当新的类型需要添加时,我们只需要实现Handler,并注册到配置文件即可,其他无需改动了 

3、我们通过Properties文件完成handler的注册

总结:以上便是我的思考,可以认为是策略模式的一种应用场景,类似于JDBC中的connection 与DriverManager,通常策略模式会用在大量出现if else的地方(《设计模式》)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: