Definition: Do not have more than one cause for class changes. In layman's terms, a class is responsible for only one responsibility.
The origin of the problem: class T is responsible for two different duties: responsibility P1, Responsibility P2. When a class T needs to be modified due to a change in the duty P1 requirements, it is possible to cause a normal function to malfunction P2 functionality.
Solution: Follow a single responsibility principle. Set up two classes T1, T2 respectively, so that T1 complete the functions P1 function, T2 complete functions P2 function. In this way, when the class T1 is modified, the responsibility is not P2 the risk of failure, and similarly, when T2 is modified, the responsibility is not P1 the risk of failure.
When it comes to the principle of single responsibility, many people will dismiss it. Because it's too easy. Inexperienced programmers who have never read design patterns and have never heard of a single principle of responsibility will consciously adhere to this important principle when designing software, because it is common sense. In software programming, no one wants to cause other functions to fail because a feature has been modified. The way to avoid this problem is to follow a single principle of responsibility. Although a single responsibility principle is so simple and considered common sense, even the program written by an experienced programmer can have code that violates this principle. Why is this happening? Because there is responsibility to spread. The so-called responsibility spread, is for some reason, the responsibility P is divided into finer granularity of responsibility P1 and P2.
For example: Class T is only responsible for a duty p, so the design is in line with the principle of single responsibility. Later for some reason, perhaps the need to change, perhaps the process of the designer of the state has improved, the need to subdivide the responsibility of P-granularity more granular responsibility p1,p2, if you want to make the procedure to follow the principle of a single responsibility, you need to break the class T also into two classes T1 and T2, respectively, responsible for P1, P2 two responsibilities. But when the program has been written, it's too time-consuming. So, simply modifying the class T and using it to take charge of two responsibilities is a good choice, although this is contrary to the principle of single responsibility. (The risk is the uncertainty of the spread of responsibility, because we would not think of this duty p, which could spread to P1,P2,P3,P4 in the future ...) Pn. So remember to refactor the code immediately before it spreads to the point where we can't control it. )
For example, use a class to describe an animal breathing the scene:
class Animal{ public void breathe(String animal){ System.out.println(animal+“呼吸空气”); } } public class Client{ public static void main(String[] args){ Animal animal = new Animal(); animal.breathe(“牛”); animal.breathe(“羊”); animal.breathe(“猪”); } }
Operation Result:
Cow Breathing air
Sheep Breathing Air
Pig Breathing air
Program on-line, found that the problem, not all animals are breathing air, such as fish is to breathe water. If you follow the principle of single responsibility when modifying, you need to subdivide the animal class into terrestrial animal terrestrial, aquatic animal aquatic, the code is as follows:
Class terrestrial{public void Breathe (String animal) {System. Out.println (animal+ "breathing air"); }} class aquatic{ public void Breathe (String animal) {System. Out.println (animal+ "Breathing Water"); }} public class client{ public static void main (string[] args) {Terrestrial terrestrial =
new terrestrial (); Terrestrial.breathe ("Ox"); Terrestrial.breathe ("sheep"); Terrestrial.breathe ("Pig"); Aquatic aquatic =
new Aquatic (); Aquatic.breathe ("Fish");}}
Operation Result:
Cow Breathing air
Sheep Breathing Air
Pig Breathing air
Fish Breathing water
We will find that if this modification costs a lot, you need to modify the client in addition to decomposing the original class. While the direct modification of the class animal to achieve the purpose of violating the single principle of responsibility, but the cost is much smaller, the code is as follows:
class animal{public void breathe (String animal) {if ("Fish". Equals (animal)) {System . out.println (animal+ "Breathing Water");} else{system. Out.println (animal+ "breathing air"); }}} public class client{public Span class= "Hljs-keyword" >static void main (String[] args) { Animal Animal = new Animal (); Animal.breathe ("Ox"); Animal.breathe ("sheep"); Animal.breathe ("Pig") ); Animal.breathe ("fish"); } }
The
can see that this is a much simpler way to modify. But there is a hidden danger: one day need to divide the fish into breathing fresh water fish and breathing sea fish, then need to modify the animal class of breathe method, and the original code changes will call "pig" "Cattle" "sheep" and other related functions risk, perhaps someday you will find the results of the program run into " Cows breathe water. " This kind of modification directly violates the principle of single duty at the code level, although it is the simplest to modify, but the hidden trouble is the biggest. There is another way to modify it:
class animal{public void breathe (String animal) {system. Out.println (animal+ "breathing air"); } public void breathe2 (String Animal) {System. Out.println (animal+ "Breathing Water"); }} public class client{public Span class= "Hljs-keyword" >static void main (String[] args) { Animal Animal = new Animal (); Animal.breathe ("Ox"); Animal.breathe ("sheep"); Animal.breathe ("Pig") ); Animal.breathe2 ("fish"); } }
As you can see, this modification does not change the original method, but instead adds a new method to the class, which violates the principle of single responsibility, but at the method level it conforms to the principle of single responsibility, because it does not move the code of the original method. Each of the three ways have advantages and disadvantages, then in the actual programming, which one to use? In fact, this is really difficult to determine, according to the actual situation. My principle is that only logic is simple enough to violate the principle of single responsibility at the code level, and only if the number of methods in the class is small enough to violate the principle of single responsibility at the method level;
For example, in this case, it is too simple, it has only one method, so it is not too much of a violation at the code level to violate the single responsibility principle or at the method level. The classes in the actual application are much more complex, and once the responsibilities are spread and the classes need to be modified, unless the class itself is very simple, it is better to follow the principle of single responsibility.
The advantages of following a single responsibility are:
Can reduce the complexity of the class, a class is responsible for only one responsibility, its logic is certainly more than the responsibility of more than the responsibility of more simple;
Improve the readability of the class, improve the maintainability of the system;
The risk of change is reduced, the change is inevitable, if a single responsibility principle is well adhered to, when a function is modified, it can significantly reduce the impact on other functions.
One thing that needs to be explained is that the single responsibility principle is not only specific to object-oriented programming, so long as it is a modular program design, it applies a single responsibility principle.
Six principles of Design pattern (1): Single duty principle