设计模式思考:模式实践
学习了这么长时间的模式,一直想实践一下,但是由于模式的理解不够,而且不能用形式化的模式,一直以来也没有好的实践机会。今天在做一个小的模块的时候(重构以前的模块),写出了一个自己觉得很不错的模块,感觉比以前来说有长足的进步,这里就来和大家分享下。
环境描述:由于在公司的做项目时,大部分是写小的模块,系统有一个框架,一般都是在系统的基础上写几个模块,就算完成一个小的项目了。但是由于大部分项目都有很多重复的代码,所以就打算自己写一个模块,以便更好更快的开发。一般的小项目都是一个单表的增删改查,功能相对来说比较单一的,然后就是验证,就是提交数据的时候的验证。无非就是改一下验证的内容,然后是数据表的不同,字段的不同,其他都大同小异,当然有的时候也有审核这样的操作,也比较类似。于是我就打算写一个封装单表的类,用以简化每次的操作,还有一个目的是将单表的数据操作都封装在一起,防止各个操作里调用数据的不统一。
先来说下以前的设计,由于这种需求,于是我就打算写一个dbtable类,它包含了数据表(table),验证文件名(validateName)(验证采用的bean方式,全部放在系统的某一个指定的文件里)这些属性,后来发现大部分表都有主键(pk)的,于是又加入了主键属性,然后里面的方法就是insert,update,delete等数据表操作,当然还有select,然后在insert,update里又加入了验证,这样客户端就能直接进行验证了,这个类里还有用主键作为查询条件的selectByPkey的方法,这样就只用传入主键值就行了,然后再写一个工厂,用来创建这个类的实例。dbtable类是一些默认的操作方法,当我有新的操作的时候,我就得采用继承的方法来加入新的方法,这个时候就用工厂创建子类的实例,如果只需要默认的增删改查时,我就把数据表,主键等属性当参数传给dbtable类,获得一个实例。类很快写好了,投放使用,开始的时候还不错,收效很好,调用代码比以前简介了很多。
好景不长。很快,一个项目里就开始犯难了。这个项目里,再验证并插入数据表数据后,还需要插入的数据,但是由于验证操作和验证返回的格式化后的数据都在父类的insert里,没办法获得这些数据了,于是这个时候我就开始重载父类的insert类了,可是调用的时候又得改变代码了,又和以前的代码差不多了,虽然这个问题也不是很大,但是这个时候,我发现这个类已经耦合了太多东西,根据这段时间看的设计模式原则,这个类负责了太多的东西,包括验证,还有pk操作(如果某个表没有主键,这个时候就尴尬了),还有一个前面忘说了,就是对于select的参数,我是采用多个参数输入然后用用内部的一个sql方法将它组合成一个完整的sql语句,这个也是耦合的,因为当我要改变默认表查询条件的时候我就得修改这个类了。总之,这个时候我已经察觉到这个类的坏味道了,再学了这么多设计模式后,我打算好好的重构它。
说干就干,马上开始从头分析这个需求。由于原来就是根据功能要求(现在想起来就是专注于实现去编程的),所以这次得先从高层需求分析。
问题:老系统中,对于一个表的查询分散各个方法中,当需要修改调用方法时(比如搜索项目,由原来的默认搜索整个项目要改成默认只搜索出开放的项目)就需要改掉所有调用的方法;还有系统调用方法较复杂,而且重复较多。
目的:对数据表的数据操作进行封装,简化数据调用操作。
本着这个目的,然后开始分析,首先是数据表类,我得写个接口,因为当系统框架更改的时候,数据库类(公司使用的adodb,有时候自己写不用框架的时候就直接使用php自带的)就不一样了,我的数据表类必须保证可以随系统更换而换,如果不是使用mysql的时候也没问题。然后就是需要把验证,pk操作,以及解析组合sql的方法给分开,思考了下,当我这么想的时候发现,将sql组合的方法分开时,这个类的复用性就很高了,它不仅能在我这个数据表类中运行,还能提供给外界使用,或者换个系统也没问题,一举两得。然后是验证和pk,我发现有时候要用到验证,有时候要用到pk,这个时候我就想到了装饰者模式,在需要的时候来将他们装饰到数据表类上去,然后再交给工厂来创建具体的实例,需要验证就加上,需要pk也可以同时加上,这样就完美了。。然后写好代码,运行测试,发现全通过了,而这个时候看看代码,跟以前比起来,发现优美太多了。而且这样扩展也更容易扩展,比如如果需要链表,就再加一个链表的装饰者上去,也不需要改现有的代码。
回顾一下这次的设计,有这样的进步是由于我的分析层次不一样,以前是针对于实现来编程,而现在则是在高层,先思考要哪写功能,然后定义借口,再根据所学的设计模式来进行分析,就能得出更好的设计。由这次我也明白了一个原则,每个对象应该对它自己负责,而且它不应该把别人的责任也包含再内,如果可以,尽量让这些责任分散开来,你会得到更好的设计。