《Design pattern Zen》 reading notes (1)
Recently, I found that I need to read some content about Design pattern, so I found the book “Zen of Design pattern” on the Internet, and summarized it while reading
This time, I first summarize the views of UML diagrams and the Single Responsibility Principle.
Foreword
Design pattern is more of a philosophy, biased towards academics, and always constructs some extreme situations to describe, just like smooth planes in physics, so we need to understand more of the philosophy, and not Try to completely replicate it in actual projects.
Understand the UML logo with one picture
The following content will involve a lot of UML diagrams. If you are not familiar with it, you can take a brief look at the following diagram.
Interface-oriented programming
** Single Responsibility Principle **
Single interface responsibility
The English name of the Single Responsibility Principle principle is Single Responsibility Principle, abbreviated as SRP.
How to divide the responsibilities of classes. Let’s take an example to illustrate what the Single Responsibility Principle is.
As long as you have done the project, you must come into contact with the modules of users, institutions, and role management. Basically, the RBAC model (Role-Based Access Control, role-based access control, grants and cancels user permissions by assigning and canceling roles, It is indeed a good solution to separate the action subject (user) from the behavior (permission) of the resource. What we want to talk about here is user management, modifying user information, increasing institutions (one person belongs to multiple institutions), increasing roles, etc. Users have so much information and behavior to maintain, we will write these into an interface. It’s all user management classes. Let’s take a look at its class diagram first
** This interface is designed to be problematic, the user’s properties and user behavior are not separated, which is a serious mistake **! This interface is indeed designed to be a mess, the user’s information should be extracted into a BO (Business Object, Business Object), the behavior extracted into a Biz (Business Logic, business logic), according to this idea of the class diagram Correction, as shown in Figure 1-2.
It is repackaged into two interfaces. IUserBO is responsible for the user’s attributes. To put it simply, the responsibility of IUserBO is to collect and feedback the user’s attribute information; IUserBiz is responsible for the user’s behavior and completes the maintenance and change of user information. You may have to say that this is still different from the User class I use in my actual work! Don’t worry, let’s first take a look at how to use split into two interfaces. OK, we are now programming for interfaces, so after generating this UserInfo object, of course you can use it as an IUserBO interface. It can also be used as an IUserBiz interface, depending on where you use it.
1 | IUserInfo userInfo = new UserInfo(); |
It can indeed be so, and the problem is solved, but let’s analyze the action just now. Why split an interface into two? In fact, in actual use, we prefer to use two different classes or interfaces: one is IUserBO and the other is IUserBiz. The class diagram is shown in the figure.
The above action of splitting an interface into two interfaces relies on the Single Responsibility Principle. What is the Single Responsibility Principle?
The Single Responsibility Principle states that there should be one and only one reason to change a class.
The Single Responsibility Principle requires us to separate our attributes from our actions.
But not only that, there is also a division of responsibilities between behaviors.
For example, we have a mobile phone, it has several functions, divided into dialing, calling, away from the keyboard, how do we design this excuse?
I believe most readers will say that there is no problem with this. I used to do it this way. It is also written in the book of XX, and the source code of what is also written in this way! Yes, this interface is close to perfection. See clearly, it is “close”! The Single Responsibility Principle requires that an interface or class has only one reason to cause changes, that is, an interface or class has only one responsibility, and it is responsible for one thing. Look at the above interface is only responsible for one thing? Is there only one reason for change? It doesn’t seem to be!
** The IPhone interface is not only one responsibility, it contains two responsibilities: one is protocol management, the other is data transmission **. The two methods of dial () and hangup () implement protocol management, which are responsible for dial-up and away from keyboard respectively; chat () realizes data transmission, converts what we say into analog or digital signals and transmits it to the other party. Then restore the signal passed by the other party to the language we understand
We can consider this question like this, will the change in protocol connection cause the change in this interface or implementation class? Yes! Will the change in data transmission (think about it, the phone can not only talk, but also surf the Internet) cause the change in this interface or implementation class? Yes! That’s very simple. There are two reasons why the class has changed. Will these two responsibilities affect each other? Telephone dialing, as long as I can connect, no matter if it’s a telecommunications or Netcom protocol. Do you still care about what data is being transmitted after the phone is connected? Through this analysis, we found that the IPhone interface on the class diagram contains two responsibilities, and the changes of these two responsibilities do not affect each other, then consider splitting it into two interfaces, as shown in the class diagram.
This class diagram looks a bit complicated and fully meets the requirements of the Single Responsibility Principle. Each interface has distinct responsibilities and a clear structure, but I believe you will definitely not use this method when designing it. A mobile phone class must be used by combining ConnectionManager and DataTransfer. Combination is a strong coupling relationship. You and I both have a common lifetime. Such a strong coupling relationship is not as good as using the interface to achieve it, and it also increases the complexity of the class, with two more classes. After thinking like this, let’s modify the class diagram
This design is perfect, one class implements two interfaces, merging two responsibilities in one class. You will feel that this Phone has caused changes for two reasons, yes, but don’t forget ** We are programming for interfaces, and we publish interfaces rather than implementation classes. **
Single category responsibility
For interfaces, we must be single in design, but for implementation classes, we need to consider many aspects. Copying the Single Responsibility Principle will cause a sharp increase in classes, bring a lot of trouble to maintenance, and overly subdivided responsibilities will artificially increase the complexity of the system. The behaviors that can be implemented by one class must be split into two classes, and then coupled together by aggregation or combination, artificially creating the complexity of the system.
Single method responsibility
Single Responsibility Principle applies to interfaces, classes, and methods. What does it mean? A method does one thing as much as possible, such as a method to change the user password. Don’t put this method in the “modify user information” method. The granularity of this method is very rough
Method responsibilities are not clear, not single, do not let others guess what logic this method may be used to deal with. A better design is shown in Figure
It can be seen from the class diagram that if you want to modify the user name, call the changeUserName method; to modify the home address, call the changeHomeAddress method; to modify the work phone, call the changeOfficeTel method. The responsibilities of each method are very clear and clear, not only is it simple to develop, but also easy to maintain in the future. Everyone can gradually develop such a habit.
Best practices
Reading this, some people may ask me, are you writing the design principles of the class? You are talking about the Single Responsibility Principle of the interface throughout, and you have violated the Single Responsibility Principle of the class! Hehe, this is really true, my original intention was to make this principle clear, the Single Responsibility Principle of the class, this is very simple, but when I wrote it back, I found that it was not the case. Looking at some previous designs and codes, basically the class designs that are available are all in line with the Single Responsibility Principle is contrary. Calm down and recall, I found that every class is designed this way for a reason. I checked Wikipedia, OODesign and other websites, and experts and I have similar experiences. Basically, the Single Responsibility Principle of classes uses a similar sentence to say “This is sometimes hard to see”, which translates to “This is sometimes hard to see”.