The single responsibility principle

One of the six principles of design patterns: the single responsibility principle

Introduction to the

Name: Single responsibility principle

Single Responsibility Principle

There should never be more than one reason for a class to change. There should be one and only one reason for a class to change… It means that no matter what I do, I only do one thing. If you tell me to go grocery shopping, I only do grocery shopping. If you tell me to take out the garbage, I don’t do it

Temper: a word “ye”, two words “especially ye”

Partner: I have a single responsibility. Where can I find my partner?

Personal introduction: In this multi-responsibility society, I seem to be so maverick, but I do not know that a lot of things happening in the society are caused by the failure to deal with responsibilities, for example, often some parents with their children, while playing mobile phones, resulting in lost children, accidents and so on

Single responsibility application scope

The single responsibility principle applies to interfaces, methods, and classes. By all accounts, interfaces and methods must guarantee a single responsibility, and classes need not, as long as they conform to the business.

methods

Consider this scenario: suppose we want to make a user to change the name and password of the function, there are many implementation schemes, for example, the following two implementation methods

Code: SrpOfMethod. Java

The first implementation

/** ** /
enum OprType {
    /** * Update password */
    UPDATE_PASSWORD,
    /** * update the name */
    UPDATE_NAME;
}

interface UserOpr {
    boolean updateUserInfo(User user, OprType oprType);
}

class UserOprImpl implements UserOpr {

    @Override
    public boolean updateUserInfo(User user, OprType oprType) {
        if (oprType == OprType.UPDATE_NAME) {
            // update name
        } else if (oprType == OprType.UPDATE_PASSWORD) {
            // update password
        }
        return true; }}Copy the code

The second implementation

/** * the correct example */
interface UserOpr2 {
    boolean updatePassword(User user, String password);
    boolean updateUserInfo(User user);
}

class UserOprImpl2 implements UserOpr2 {

    @Override
    public boolean updatePassword(User user, String password) {
        user.setPassword(password);
        // update password
        return true;
    }

    @Override
    public boolean updateUserInfo(User user) {
        // update user info
        return true; }}Copy the code

What is the difference between the two implementations? The first implementation uses the OprType to do different things. Coupling the password change with the name change can cause problems. If you’re not careful, you can’t see what you’re doing directly in the code, so the responsibility of this method is unclear. In the second implementation, password and name changes are separated, so that password and name changes are treated as a separate responsibility. This way, it is very clear that whichever method you call, you know exactly what logic the method is implementing. The conclusion? The second approach is consistent with the single responsibility principle. In reality, seeing a lot of code like the first implementation, and there are dozens of enumerations, can be a struggle to look at the code.

interface

Imagine this scenario. Suppose we ask Xiao Ming to take out the garbage, And Xiao Hong to buy vegetables. After Xiao Hong comes back, she asks Xiao Hong to wash the dishes. Here are also two implementation examples.

Code: SrpOfInterface. Java

The first implementation

/** ** /
interface Housework {
    void shopping(a);
    void pourGarbage(a);
}

class XiaoMing implements Housework {

    @Override
    public void shopping(a) {
        / / not shopping
    }

    @Override
    public void pourGarbage(a) {
        System.out.println("pourGarbage ..."); }}class XiaoHong implements Housework {

    @Override
    public void shopping(a) {
        System.out.println("shopping ...");
    }

    @Override
    public void pourGarbage(a) {
        // Never take out the garbage}}Copy the code

Halfway back to xiao Hong to wash dishes, how to achieve? The Washington up () method is added to the Housework interface, and xiao Ming and Xiao Hong both implement the dishwashing method in turn, but Xiao Ming does not do the specific implementation code, which is very awkward, does not conform to the single responsibility principle, modify one place, does not affect the other places that do not need to change. Only make changes where needed. Xiao Ming didn’t have to wash dishes, but he had to do it.

The second implementation

/** * the correct example */
interface Shopping {
    void doShopping(a);
}

interface PourGarbage {
    void doPourGarbage(a);
}

interface WashingUp {
    void doWashingUp(a);
}

class XiaoMing2 implements PourGarbage {

    @Override
    public void doPourGarbage(a) {
        System.out.println("pourGarbage ..."); }}class XiaoHong2 implements Shopping.WashingUp {

    @Override
    public void doShopping(a) {
        System.out.println("shopping ...");
    }

    @Override
    public void doWashingUp(a) {
        System.out.println("washing up ..."); }}Copy the code

It can be seen that this kind of implementation separates different housework as different responsibilities. This kind of implementation can realize the types of housework as needed. Xiao Ming only needs to take out the garbage to realize the PourGarbage interface, while Xiao Hong only needs to go Shopping and wash dishes to realize the Shopping and WashingUp interface. It doesn’t affect the other party at all, and that’s perfect code written under the single responsibility principle.

class

Class this looked at some information said that there is no hard requirement must be divided by a single responsibility principle, or the responsibility of the class can be large or small, there is no very clear like the above interface in accordance with a single responsibility principle is very clear and very reasonable. Consider this scenario: We want to implement a user registration, login, and logout operations, which can be implemented in two ways

Code: SrpOfClass. Java

The first implementation

From the user’s point of view, these actions are user actions and can be placed in a unified class, UserBiz

class UserBiz {

    public boolean register(User user){
        // Register operation
        return true;
    }

    public boolean login(User user) {
        // Login operation
        return true;
    }

    public boolean logout(User user) {
        // Log out
        return true; }}Copy the code

The second implementation

And some people say, isn’t it a single responsibility? For service operations, you need to separate registration, login, and logout

class UserRegisterBiz {

    public boolean register(User user){
        // Register operation
        return true; }}class UserLoginBiz {

    public boolean login(User user) {
        // Login operation
        return true; }}class UserLogoutBiz {

    public boolean logout(User user) {
        // Log out
        return true; }}Copy the code

Feel like in the bar, in fact, there is no good or bad, according to the specific business specific analysis, you said your login, registration, logout operation code is a lot, need to separate, then separate, there is no fault.

benefits

  1. Class complexity is reduced, and what responsibilities are implemented are clearly defined
  2. Readability goes up, complexity goes down, of course readability goes up
  3. Increased maintainability, improved readability, and of course easier to maintain
  4. To reduce the risk caused by change, change is essential. If the single responsibility of the interface is done well, an interface modification only affects the corresponding implementation class and has no impact on other interfaces, which greatly helps the scalability and maintenance of the system (Zen of Design Patterns).

conclusion

The purpose of this single responsibility principle is to improve the maintainability, readability, and extensibility of the code, and it may not be worth it to break these three features for the sake of a single responsibility.

References: Big Talk Design Patterns, Java Design Patterns, Zen Of Design Patterns, Grinding Design Patterns, Head First Design Patterns

I hope this article will be helpful to you. The design Pattern series will be updated continuously. Interested students can follow the official account and get the article to be pushed to read in the first time.

The public account design pattern series article