![设计模式就该这样学:基于经典框架源码和真实业务场景](https://wfqqreader-1252317822.image.myqcloud.com/cover/758/33114758/b_33114758.jpg)
4.2 为什么一定要学习设计模式
先来看一个生活案例,当我们开心时,也许会寻求享乐。在学习设计模式之前,你可能会这样感叹:
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_2.jpg?sign=1739296020-cXkD32y0MZIigyy3cuzFuEWMtj1UyMRy-0-f2e8f6c75165f36e10c7e5023cb461ae)
学完设计模式之后,你可能会这样感叹:
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_3.jpg?sign=1739296020-4tHcvDpsm61cB6pdRs9kIjWlpOL2mhTx-0-21ee65014c7120b5a29b669b36b51866)
大家对比一下前后的区别,有何感受?
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_4.jpg?sign=1739296020-fOh4IPpI56Jol8MlGYqBXKEonnRsZEEz-0-5c54055ed30ec75c99ddb24dcd356216)
回到代码中,我们来思考一下,设计模式能解决哪些问题?
4.2.1 写出优雅的代码
先来看一段笔者很多年前写的代码。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_5.jpg?sign=1739296020-7J5WB0QDE1x4gbafudhgU3qwy448tVFx-0-a2a88ed854b5fba12acb00cf5724ce36)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_6.jpg?sign=1739296020-RjasTK22TDnFpq5k3ze6lWwPgeSD5RkB-0-2e73bf7151ca9356917911fac428af4b)
优化之后的代码如下。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_7.jpg?sign=1739296020-GkHGrUF50fef0pSG8qS4ULbLqfc0TOqt-0-529bf104d14d78a2bd722908e3fffa84)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_8.jpg?sign=1739296020-AvpHeg3uG1szVyBbpGwxsmrIxIMlS3PW-0-1d7b9633fe9a47c5aa94bb01692ddbfe)
4.2.2 更好地重构项目
平时我们写的代码虽然满足了需求,但往往不利于项目的开发与维护,以下面的JDBC代码为例。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_9.jpg?sign=1739296020-Kt5wIHf08HjI717oT2GUMO6guKYTSIEn-0-5dc7559789b443468ed4b9970c13ffac)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_10.jpg?sign=1739296020-mjch4pXE0Y8ScQONiogh9FjORyTgv3Xk-0-9c1f896fb8e7b3f57f2eb86ef078644d)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_11.jpg?sign=1739296020-M9We4YSzhPRTZouHP82asshEdgwHKO0Q-0-1fbdb5e1408585adf6abf03fe3920cf4)
上述代码的功能没问题,但是代码重复得太多,因此可以进行抽取,把重复代码放到一个工具类JdbcUtil里。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_12.jpg?sign=1739296020-7CqpzTnqzTXbQZKbCscM5gsMjiX4M4hn-0-1539be0cf73280a722175d5f7d353622)
只需要在实现类中直接调用工具类JdbcUtil中的方法即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_13.jpg?sign=1739296020-tTAqvW7O0cFdZbvAaod7GGMr0AXMRHws-0-2da8eb0f3892be43e475d0c23a655cd5)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_14.jpg?sign=1739296020-v4o3YYgs6emodjiFaxq3HYlFHXbHg1gx-0-002292a92cf7a00dc54b2ef2817bf548)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_15.jpg?sign=1739296020-o6fJPwCRPifYo97JuM5cI993IoOH8VOE-0-47744adeeb59af75f9fbbc84ca982c4f)
虽然完成了重复代码的抽取,但数据库中的账号、密码等直接显示在代码中,不利于后期账户密码改动的维护。可以建立一个db.propertise文件,用来存储这些信息。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_16.jpg?sign=1739296020-lNlKkpbQDrcdLYhwK20i8cO03Pw89VFa-0-675fc388b7734e09b5e1d3342429e9e4)
只需要在工具类JdbcUtil中获取里面的信息即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_17.jpg?sign=1739296020-SGGaTEyJ1MhlbUSaYNhiTKOd3ZkPjRJm-0-97f2d5e68760cacba0e7b3c2bd9cb74e)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_18.jpg?sign=1739296020-OKkoX3KsEzJm7hR1gAIMla6mQ9m74ToY-0-27de2e236c86bb24e05a2213e092c1c1)
代码抽取到这里,貌似已经完成,但在实现类中,依然存在部分重复代码,在DML操作中,除了SQL和设置值的不同,其他都相同,把相同的部分抽取出来,把不同的部分通过参数传递进来,无法直接放在工具类中。此时,可以创建一个模板类JdbcTemplate,创建一个DML和DQL的模板来对代码进行重构。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_19.jpg?sign=1739296020-dZJEsmiavDvjZOm8OQGQYGaUSUKK1BQZ-0-0082f17d1b1a552a5fa08b5e39b2e2e1)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_20.jpg?sign=1739296020-eKDBlqJxnVnscOd3uboDtCnFuc3QXduc-0-eecd76a8f1968884a4a099e4cc2d670b)
实现类直接调用方法即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_21.jpg?sign=1739296020-vG25LM2OM64VBBDI9TdFwaUlQVJExnVy-0-92e0a71d2809cb8f4cdee2c52c2af115)
这样重复的代码基本就解决了,但有一个很严重的问题,就是这个程序DQL操作中只能处理Student类和t_student表的相关数据,无法处理其他类,比如Teacher类和t_teacher表。不同的表(不同的对象)应该有不同的列,不同列处理结果集的代码就应该不一样,处理结果集的操作只有DAO自己最清楚。也就是说,处理结果的方法根本就不应该放在模板方法中,应该由每个DAO自己来处理。因此,可以创建一个IRowMapper接口来处理结果集。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_22.jpg?sign=1739296020-WgOMZI6P8MnITczjZbLZXu25bUlO3buX-0-74e46171bf47d95cff2ede0a1d7d0bfe)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_23.jpg?sign=1739296020-TqtXBUV67aBe43J7zyL91rkAVt11mX3O-0-6911b841b9a5e23a101952f8a2475d92)
DQL模板类中调用IRowMapper接口中的handle方法,提醒实现类自己去实现mapping方法。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_24.jpg?sign=1739296020-leKXuLbUHfwL2rqC5auyS7zSrQEhb4Ak-0-41726871b10365c3b0a0c3602211a1e4)
实现类自己去实现IRowMapper接口的mapping方法,想要处理什么类型的数据在里面定义即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_25.jpg?sign=1739296020-EUfdki6UEYXnepkaXS6jlTkWJkbHmTvX-0-76f4ba7edf71ca859d6fd01be30e150b)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_26.jpg?sign=1739296020-qOcNsLiDix3RiNOKriXG6iSQHHD9YFGY-0-45613ac11698223e4d88675a4db4c8b3)
到这里为止,实现ORM的关键代码已经大功告成,但是DQL查询不单单要查询学生信息(List类型),还要查询学生数量,这时就要通过泛型来完成。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_27.jpg?sign=1739296020-abFkiQINrgPXflUxWiQTlDU3LCQolCLC-0-375ce8a6e659349ded7f2a16e18e36eb)
StudentRowMapper类的代码如下。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_28.jpg?sign=1739296020-tXb9xGANVi5VyEQiLErsHLg0YlPRkjoS-0-0e6a154d11eb2826664726fcbd9019e9)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_29.jpg?sign=1739296020-8TBLxGOkesUn3M4HRO2Putep2hFWJpcf-0-82256d5a8a40367668ab0020c56325f7)
这样,不仅可以查询List,还可以查询学生数量。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_30.jpg?sign=1739296020-OB4EXVTJQZe2vY9zPh04EGIBpoq1rop6-0-197ba9a98b990a636686dab1eb9fa34a)
这样,重构设计就已经完成,好的代码能让我们以后维护更方便,因此学会对代码重构是非常重要的。
4.2.3 经典框架都在用设计模式解决问题
比如,Spring就是一个把设计模式用得淋漓尽致的经典框架。本书会结合JDK、Spring、MyBatis、Netty、Tomcat、Dubbo等经典框架的源码对设计模式展开分析,帮助大家更好、更深入地理解设计模式在框架源码中的落地。