《Spring5核心原理与30个类手写实战》阅读笔记
目录
PART1 写在前面的废话
文中例子改编简化于原文实例,初衷仅为辅助自己阅读理解,若有缘看到此文,有助则万幸,无助就下次再见。学了也学不懂但还是尝试看一下。
ps.本菜鸡的新系列《学了也学不懂》那啥,可恶啊,这次一定会坚持学下去。
PART2 软件架构设计原则
先简单理解
1、开闭原则:程序对修改关闭,对拓展开放。
2、依赖倒置原则:上层不依赖下层模块。
3、单一职责原则:一个类负责一件事。
4、接口隔离原则:接口不复杂,细化接口,方法尽量少(但不是越少越好)。
5、迪米特原则:最少知道原则,一个对象保持对一个对象最少的了解,只和自己相关的对象交流。
6、里氏替换原则:子类拓展符类功能,但不能改变父类原有功能。
7、合成服用原则:尽量使用对象组合/聚合,而不是继承关系达到软件复用
聚合:如汽车类中包含轮胎类,引擎类,聚合成一辆车
public class Car
{
private Engine engine;
private Wheel wheel;
public Car(Engine engine, Wheel wheel)
{
this.engine = engine;
this.wheel = wheel;
}
}
组合:部分共同构成整体,如鼻子眼睛等构成了脸,脸没了鼻子眼睛都没了
public class Face
{
private Eyes eyes;
private Nose nose;
public Face()
{
eyes = new Eyes();
nose = new Nose();
}
}
PART3 一个重构代码的例子
针对原书中对数据库操作例子的简化模拟
模拟数据库增删改操作
假设此段为平时写的代码,满足了需求但是不利于开发与维护,而且存在很多重复的代码。
@Service
public class CommonService {
public void save(Student stu){
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
//3.模拟保存数据
String sql = "insert";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//4.模拟关闭数据源
System.out.println("模拟数据源关闭");
}
public void delete(Student stu){
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
//3.模拟删除数据
String sql = "delete";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//4.模拟关闭数据源
System.out.println("模拟数据源关闭");
}
public void update(Student stu){
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
//3.模拟更新数据
String sql = "update";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//4.模拟关闭数据源
System.out.println("模拟数据源关闭");
}
}
2.上述代码重复较多,进行重复代码提取,将重复的代码放入工具类DataUtils 中,实现类CommonService2可直接调用工具类中的方法。
//工具类
public class DataUtils {
private DataUtils(){}
static {
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
}
public static Map<String , Student> getDataSource(){
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
return dataSource;
}
public static void close(){
//模拟关闭数据源
System.out.println("模拟数据源关闭");
}
}
//实现类
@Service
public class CommonService2 {
public void save(Student stu){
//模拟加载数据库取动相关
Map<String , Student> dataSource = DataUtils.getConnection();
//模拟保存数据
String sql = "insert";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//模拟关闭数据源
DataUtils.close();
}
public void delete(Student stu){
//模拟加载数据库取动相关
Map<String , Student> dataSource = DataUtils.getConnection();
//模拟删除数据
String sql = "delete";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//模拟关闭数据源
DataUtils.close();
}
public void update(Student stu){
//模拟加载数据库取动相关
Map<String , Student> dataSource = DataUtils.getConnection();
//模拟更新数据
String sql = "update";
System.out.println("模拟执行sql");
dataSource.put(sql,stu);
//模拟关闭数据源
DataUtils.close();
}
}
4.第一阶段完成,但是实现类中仍然存在重复的代码,上个实现类CommonService2 中,除了模拟的需要执行的sql不同,其他对数据库相关的模拟操作都是相同的,故将对数据库相关的一些操作进行抽取,放入模板类中DataTemplate ,实现类直接调用对应的方法进行对数据库的操作。
public class DataTemplate {
//对数据库操作统一处理
public static List<Student> update(String sql, Student stu){
List<Student> list = new ArrayList<>();
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
//3.模拟sql执行
String sqlStatement = sql;
System.out.println(sqlStatement);
//假设此步为执行sql方法
dataSource.put(sql,stu);
//模拟关闭数据源
System.out.println("模拟数据源关闭");
list.add(stu);
return list;
}
}
@Service
public class CommonService3 {
public void save(Student stu){
String sql = "insert";
DataTemplate.update(sql,stu);
}
public void delete(Student stu){
String sql = "delete";
DataTemplate.update(sql,stu);
}
public void update(Student stu){
String sql = "update";
DataTemplate.update(sql,stu);
}
}
5.到此阶段,重复的代码基本处理好了,虽然做好了封装,但是此时只能处理student类,而不能处理其他类,并且实际情况中,不同类的类字段不同,结果集也不同,所以具体的类不应该出现在模板中,考虑将模板改造成通用的,不同类的处理交给对应DAO来处理,创建IDataMapper接口用于处理结果集。
public interface IDataMapper {
//结果处理
List dataMapper(Student stu);
}
public class StudentMapper implements IDataMapper {
@Override
public List dataMapper(Student stu) {
//模拟处理student类型的结果
List<Student> list = new ArrayList<>();
list.add(stu);
return list;
}
}
public class DataTemplate {
//对数据库操作统一处理
public static List<Student> update2(String sql, IDataMapper mapper, Student stu){
List<Student> list = new ArrayList<>();
//1.模拟加载数据库取动相关
System.out.println("模拟数据库取动加载");
//2.模拟创建数据库连接
Map<String , Student> dataSource = new HashMap<>();
//3.模拟sql执行
String sqlStatement = sql;
System.out.println(sqlStatement);
//假设此步为执行sql方法
dataSource.put(sql,stu);
//模拟关闭数据源
System.out.println("模拟数据源关闭");
return mapper.dataMapper(stu);
}
}
@Service
public class CommonService4 {
public List<Student> get(Student stu){
String sql = "select";
return DataTemplate.update2(sql,new StudentMapper(),stu);
}
}
6.再继续修改相关类型为泛型,从而实现可以对不同的类进行查询
public class Teacher {
private String id;
private String course;
}
public class TeacherMapper implements IDataMapper<Teacher> {
@Override
public List<Teacher> dataMapper(Teacher teacher) {
List<Teacher> list = new ArrayList<>();
list.add(teacher);
return list;
}
}
@Service
public class CommonService5 {
//获取学生数据
public List<Student> get(Student stu){
String sql = "select";
return DataTemplate.update2(sql,new StudentMapper(),stu);
}
//获取老师数据
public List<Teacher> get(Teacher teacher){
String sql = "select";
return DataTemplate.update2(sql,new TeacherMapper(),teacher);
}
}
到此重构完成。