Reading notes on the core principles of spring 5 and handwriting practice of 30 classes
catalogue
PART1 is written in front of the nonsense
PART2 software architecture design principles
PART3 is an example of refactoring code
PART1 is written in front of the nonsense
The example in the article is adapted and simplified to the original example. The original intention is only to assist yourself in reading and understanding. If you are lucky to see this article, it will help. If you are helpless, see you next time. I can't understand it, but I still try to see it.
ps. the new series of chicken with this dish "I can't understand after learning". Damn it, I'll stick to it this time.
PART2 software architecture design principles
First, simply understand
1. Opening and closing principle: the program is closed to modification and open to expansion.
2. Dependency Inversion Principle: the upper layer does not depend on the lower module.
3. Single responsibility principle: one class is responsible for one thing.
4. Interface isolation principle: the interface is not complex, the interface is refined, and the methods are as few as possible (but the less the better).
5. Dimitri's principle: the principle of least knowledge. An object keeps the least understanding of an object and communicates only with its own related objects.
6. Richter's substitution principle: the subclass expands the function of the symbol class, but cannot change the original function of the parent class.
7. Composition principle: try to use object composition / aggregation instead of inheritance relationship to achieve software reuse
Aggregation: for example, the automobile category includes tires and engines, which are aggregated into one vehicle
public class Car { private Engine engine; private Wheel wheel; public Car(Engine engine, Wheel wheel) { this.engine = engine; this.wheel = wheel; } }
Combination: some parts together form a whole, such as nose and eyes, which form the face. Without the face, the nose and eyes are gone
public class Face { private Eyes eyes; private Nose nose; public Face() { eyes = new Eyes(); nose = new Nose(); } }
PART3 is an example of refactoring code
Simplified simulation of database operation examples in the original book
Simulate database addition, deletion and modification
It is assumed that this section is the code written at ordinary times, which meets the requirements, but is not conducive to development and maintenance, and there are many duplicate codes.
@Service public class CommonService { public void save(Student stu){ //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); //3. Save simulation data String sql = "insert"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //4. Simulate closing the data source System.out.println("Analog data source shutdown"); } public void delete(Student stu){ //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); //3. Simulate deletion of data String sql = "delete"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //4. Simulate closing the data source System.out.println("Analog data source shutdown"); } public void update(Student stu){ //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); //3. Simulation update data String sql = "update"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //4. Simulate closing the data source System.out.println("Analog data source shutdown"); } }
2. The above codes are repeated frequently. Extract the repeated codes and put the repeated codes into the tool class DataUtils In, the implementation class CommonService2 can directly call the methods in the tool class.
//Tool class public class DataUtils { private DataUtils(){} static { //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); } public static Map<String , Student> getDataSource(){ //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); return dataSource; } public static void close(){ //Analog shutdown data source System.out.println("Analog data source shutdown"); } } //Implementation class @Service public class CommonService2 { public void save(Student stu){ //Simulation loading database fetching related Map<String , Student> dataSource = DataUtils.getConnection(); //Simulation save data String sql = "insert"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //Analog shutdown data source DataUtils.close(); } public void delete(Student stu){ //Simulation loading database fetching related Map<String , Student> dataSource = DataUtils.getConnection(); //Simulate deletion of data String sql = "delete"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //Analog shutdown data source DataUtils.close(); } public void update(Student stu){ //Simulation loading database fetching related Map<String , Student> dataSource = DataUtils.getConnection(); //Simulation update data String sql = "update"; System.out.println("Simulated execution sql"); dataSource.put(sql,stu); //Analog shutdown data source DataUtils.close(); } }
4. The first stage is completed, but there are still duplicate codes in the implementation class. In the previous implementation class CommonService2, except for the sql to be executed for simulation, other simulation operations related to the database are the same. Therefore, some operations related to the database will be extracted and put into DataTemplate in the template class, The implementation class directly calls the corresponding method to operate the database.
public class DataTemplate { //Unified processing of database operations public static List<Student> update(String sql, Student stu){ List<Student> list = new ArrayList<>(); //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); //3. Simulate sql execution String sqlStatement = sql; System.out.println(sqlStatement); //Suppose this step is to execute the sql method dataSource.put(sql,stu); //Analog shutdown data source System.out.println("Analog data source shutdown"); 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. At this stage, the repeated code is basically handled. Although it is encapsulated, at this time, only student classes can be processed, not other classes. In fact, the class fields of different classes are different, and the result sets are also different. Therefore, specific classes should not appear in the template. Consider transforming the template into a general one, and handing over the processing of different classes to the corresponding DAO, Create the IDataMapper interface to process the result set.
public interface IDataMapper { //Result processing List dataMapper(Student stu); } public class StudentMapper implements IDataMapper { @Override public List dataMapper(Student stu) { //Simulate the results of processing student types List<Student> list = new ArrayList<>(); list.add(stu); return list; } } public class DataTemplate { //Unified processing of database operations public static List<Student> update2(String sql, IDataMapper mapper, Student stu){ List<Student> list = new ArrayList<>(); //1. Simulation loading database fetching System.out.println("Simulate database fetching and loading"); //2. Simulate creating database connection Map<String , Student> dataSource = new HashMap<>(); //3. Simulate sql execution String sqlStatement = sql; System.out.println(sqlStatement); //Suppose this step is to execute the sql method dataSource.put(sql,stu); //Analog shutdown data source System.out.println("Analog data source shutdown"); 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. Continue to modify the relevant type to generic, so that different classes can be queried
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 { //Get student data public List<Student> get(Student stu){ String sql = "select"; return DataTemplate.update2(sql,new StudentMapper(),stu); } //Get teacher data public List<Teacher> get(Teacher teacher){ String sql = "select"; return DataTemplate.update2(sql,new TeacherMapper(),teacher); } }
This completes the refactoring.