- 设计模式就该这样学:基于经典框架源码和真实业务场景
- 谭勇德(Tom)
- 975字
- 2021-04-01 07:37:58
4.2 为什么一定要学习设计模式
先来看一个生活案例,当我们开心时,也许会寻求享乐。在学习设计模式之前,你可能会这样感叹:
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_2.jpg?sign=1739426702-CD7lMXCOZERKiki2uo69AW9e3vLa5N6h-0-97e4931e270e55b8ac4ac1aae4eb842b)
学完设计模式之后,你可能会这样感叹:
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_3.jpg?sign=1739426702-3awFN5lXikmvWqynepbMztdO0mZAnFGT-0-f6ad3f867fa46288c51f9236e99384f4)
大家对比一下前后的区别,有何感受?
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_4.jpg?sign=1739426702-x0BKgcsL6txhzxsvLQ7Hw4mekiYcqPX0-0-034a61ea4962b6c14c78e7868a492067)
回到代码中,我们来思考一下,设计模式能解决哪些问题?
4.2.1 写出优雅的代码
先来看一段笔者很多年前写的代码。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_5.jpg?sign=1739426702-FuZnJLjb6ebyChnn2VYmeRogRUZ4YUDd-0-4b2bd67132afbd4fc12bec44bc9d7c12)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_6.jpg?sign=1739426702-sZ8aRReASoX4Ux0OaabMHq8TYlgAKKbr-0-1ca041a23fa072f90c1856ea71475ec3)
优化之后的代码如下。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_7.jpg?sign=1739426702-vWu0EwZL8VG8J6Ckny0Bv2ZMsG52FnwC-0-5b8014cad680440b3df9c4f2abadb75e)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_8.jpg?sign=1739426702-fiQWCXZ2ybvaaAIOUA61w3hyIKTAAMpX-0-a5c66bf9faac57415c897caa2ab538ba)
4.2.2 更好地重构项目
平时我们写的代码虽然满足了需求,但往往不利于项目的开发与维护,以下面的JDBC代码为例。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_9.jpg?sign=1739426702-3qKPEhZdHTGjecdMWNaedRqEe8u4ftU1-0-50f5cdee887d621bd26b89a9503b9da7)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_10.jpg?sign=1739426702-JNJRYE2r03EPv2OPAqAba26MrMO1T6qz-0-1f97b5c367917e3aa0917cdaaeb621fa)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_11.jpg?sign=1739426702-seggz7uJVwP5Tch3kXN4qo0jBBnn1PKU-0-afe9c12e440a4dfa4450ca0af30e3c74)
上述代码的功能没问题,但是代码重复得太多,因此可以进行抽取,把重复代码放到一个工具类JdbcUtil里。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_12.jpg?sign=1739426702-bsXYpdsv432r7WxhCe8pMtGpovhP8DQj-0-a597b199ff0821e4e9d9a2d0dc8586ac)
只需要在实现类中直接调用工具类JdbcUtil中的方法即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_13.jpg?sign=1739426702-zwLWhpDrj9mYteG5i3Kuj0gY1WAHTeQe-0-f749ba93a68f92d3002fcbbceedc56f0)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_14.jpg?sign=1739426702-4z97UjTzd13vkva7lJtHci482JRAfI25-0-247fe1f6dccf08f675b3926e7b0d815a)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_15.jpg?sign=1739426702-FzSl2QiF1VxRr2D7WyI4f0kKXYEpMBtJ-0-6c18999cb99210a00f57e4150f6868aa)
虽然完成了重复代码的抽取,但数据库中的账号、密码等直接显示在代码中,不利于后期账户密码改动的维护。可以建立一个db.propertise文件,用来存储这些信息。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_16.jpg?sign=1739426702-Pstszxrc8B03PGsa67Mz0gjmTLiuK8zj-0-0b72997028c8dcbe70b4117dee514bb7)
只需要在工具类JdbcUtil中获取里面的信息即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_17.jpg?sign=1739426702-H19y6XKq66Nls6DM0S7Kf4LwvGB4x0pK-0-3ff483f3fe39867bc00ab23d8eace61d)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_18.jpg?sign=1739426702-r74eeVfN5FixOpAaFMvN8LvCbdi4ySBe-0-2478e862907fe865c22297807077863f)
代码抽取到这里,貌似已经完成,但在实现类中,依然存在部分重复代码,在DML操作中,除了SQL和设置值的不同,其他都相同,把相同的部分抽取出来,把不同的部分通过参数传递进来,无法直接放在工具类中。此时,可以创建一个模板类JdbcTemplate,创建一个DML和DQL的模板来对代码进行重构。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_19.jpg?sign=1739426702-2QnGvRmMTr1Vnb7RPU2NEzRll95Sf3CI-0-6dfb0078024ac7a7073278c3e63fc7b0)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_20.jpg?sign=1739426702-npJtFlL87voZk9K22pz7sYPohfbn88Ca-0-c33086f3779ba316251963f83953aa05)
实现类直接调用方法即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_21.jpg?sign=1739426702-5564INQnw3r0qBN6LS2rH12nNXUGC9Zu-0-6b6278e8c643a64ef73f06534e5a52a6)
这样重复的代码基本就解决了,但有一个很严重的问题,就是这个程序DQL操作中只能处理Student类和t_student表的相关数据,无法处理其他类,比如Teacher类和t_teacher表。不同的表(不同的对象)应该有不同的列,不同列处理结果集的代码就应该不一样,处理结果集的操作只有DAO自己最清楚。也就是说,处理结果的方法根本就不应该放在模板方法中,应该由每个DAO自己来处理。因此,可以创建一个IRowMapper接口来处理结果集。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_22.jpg?sign=1739426702-z7J5OOo0KseFFTxGVMucG3FG6XMZW8QF-0-21262992d5651a50cd4c95b30ea3a2ee)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_23.jpg?sign=1739426702-ceIPOdjp0PoHbJBqlgt8XHbUtDqmsPMo-0-64794f4fb6f6f6829da7faef5908969e)
DQL模板类中调用IRowMapper接口中的handle方法,提醒实现类自己去实现mapping方法。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_24.jpg?sign=1739426702-vJSieAyntKqx16B30iZqnxQSkrFpV7xF-0-f9dec7a23a6c83632057fffdb05722f8)
实现类自己去实现IRowMapper接口的mapping方法,想要处理什么类型的数据在里面定义即可。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_25.jpg?sign=1739426702-fb6gU9UKCZJCB5Hog71bDyOPM5HAS0iF-0-e2c285b0e02e0cb8ccb05fd4bcd6ce40)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_26.jpg?sign=1739426702-RL20X9dsgAt2wW5PGFwK5Svmcwqla84u-0-1b0e79c39b718280973119ec90c12f92)
到这里为止,实现ORM的关键代码已经大功告成,但是DQL查询不单单要查询学生信息(List类型),还要查询学生数量,这时就要通过泛型来完成。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_27.jpg?sign=1739426702-ufXsasG4jDH8XABZTRR9twYGkkoX7T9H-0-82d1fc16ca725b56044521c6479ed6b7)
StudentRowMapper类的代码如下。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_28.jpg?sign=1739426702-U76bb1g8xjKUUo1UU7d9cXDC2gKoM8Ws-0-b757d6500204944a264e94051e57ed2a)
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_29.jpg?sign=1739426702-7tn7bRlegf8Oic4eq7oeCzHTAjMtV1pa-0-75c1f5dfbd9971d24ac15d5a0bd20ca7)
这样,不仅可以查询List,还可以查询学生数量。
![img](https://epubservercos.yuewen.com/A1F36C/17725769807799506/epubprivate/OEBPS/Images/txt005_30.jpg?sign=1739426702-5Cszvg3Qyh8Sr6WMchOPqUOswSK7MlGm-0-f6f7b018fa0cca88650fde9e6a1a15c2)
这样,重构设计就已经完成,好的代码能让我们以后维护更方便,因此学会对代码重构是非常重要的。
4.2.3 经典框架都在用设计模式解决问题
比如,Spring就是一个把设计模式用得淋漓尽致的经典框架。本书会结合JDK、Spring、MyBatis、Netty、Tomcat、Dubbo等经典框架的源码对设计模式展开分析,帮助大家更好、更深入地理解设计模式在框架源码中的落地。