Back then, I was also a big fan of if/else interwriting. Here is an SAO operation, such as a simple chestnut that is easy to understand:

Generally speaking, our normal background management system has the so-called role concept, different administrator permissions are not the same, can exercise the operation is not the same, such as:

  • System Administrator (
    ROLE_ROOT_ADMIN) :
    AOperation permissions
  • Order Manager (
    ROLE_ORDER_ADMIN) :
    BOperation permissions
  • Common user (ROLE_NORMAL) : has the C operation permission

For example, when a user comes in and we need to determine the behavior of different users based on their roles, the SAO code appears:

publicclassJudgeRole{
publicString judge( String roleName ) {String result = "";if(roleName.equals("ROLE_ROOT_ADMIN"// The system administrator has A permission result ="ROLE_ROOT_ADMIN: "+ "has AAA permission"; } elseif( roleName.equals("ROLE_ORDER_ADMIN"// The order manager has B permission result ="ROLE_ORDER_ADMIN: "+ "has BBB permission"; } elseif( roleName.equals("ROLE_NORMAL"// Common user has C permission result ="ROLE_NORMAL: "+ "has CCC permission"; }else{            result = "XXX"; }return result;}
}Copy the code

So when there are dozens of characters in the system, the dozens of if/else nesting can be very sour… This is very inelegant and difficult for others to read; Second, if it is more complicated, or want to add conditions, it is not good to expand; And a code change, the old function must be retested before, not crazy…

So, how do you deal with these annoying if/else statements without reading?

Of course, some people will say that switch/case is not more elegant writing. The answer is: no difference at all!

Let’s talk a little bit about some of the ways we can improve this, and not just if/else

Why not use enumerations

There is obviously a correspondence between what character does what, so why not use the enumeration you learned?


First, define a common interface RoleOperation, which represents the operations that different roles can do:

publicinterfaceRoleOperation{String op(); // Indicate what op operations a role can do}Copy the code


RoleEnum (RoleEnum, RoleEnum, RoleEnum, RoleEnum, RoleEnum, RoleEnum);

PublicenumRoleEnumimplementsRoleOperation {/ / system administrator (have A operation privileges) ROLE_ROOT_ADMIN {@ OverridepublicStringop() {return"ROLE_ROOT_ADMIN:"+ " has AAA permission"; ROLE_ORDER_ADMIN {@overridePublicString}}, // Order manager (with B operation permission) ROLE_ORDER_ADMIN {@overridePublicStringop() {return"ROLE_ORDER_ADMIN:"+ " has BBB permission"; }}, // Common user (with C operation permission) ROLE_NORMAL {@overridePublicStringop() {return"ROLE_NORMAL:"+ " has CCC permission"; }}; }Copy the code


Then the call becomes incredibly simple, a single line of code, and the if/else goes up in smoke:

PublicclassJudgeRole {publicString judge(String roleName) { Before theif/elseDidn't!returnRoleEnum.valueOf(roleName).op(); }}Copy the code


And that way, if I want to extend the conditions later, I can just add code to the enumeration class instead of changing the previous code, which is pretty stable!

In addition to eliminating if/else with enumerations, the factory pattern can also be implemented


Why not use factory mode when there is one

Different branches doing different things provide an obvious opportunity to use the factory pattern. We just need to define the different cases individually and aggregate them in the factory class.

First, define separate business classes for different roles:

/ / the system administrator (have A operation privileges) publicclassRootAdminRoleimplementsRoleOperation {privateString roleName; publicRootAdminRole( String roleName ) {this.roleName = roleName; } @OverridepublicStringop() {return roleName + " has AAA permission"; }}Copy the code
/ / order administrator (B operation privileges) publicclassOrderAdminRoleimplementsRoleOperation {privateString roleName; publicOrderAdminRole( String roleName ) {this.roleName = roleName; } @OverridepublicStringop() {return roleName + " has BBB permission"; }}Copy the code
/ / ordinary users (C operation permissions) publicclassNormalRoleimplementsRoleOperation {privateString roleName; publicNormalRole( String roleName ) {this.roleName = roleName; } @OverridepublicStringop() {return roleName + " has CCC permission"; }}Copy the code


Write a factory class called RoleFactory to aggregate the above roles:

publicclassRoleFactory{staticMap<String, RoleOperation> roleOperationMap = newHashMap<>(); Static {roleOperationMap.put() {roleOperationMap.put() {roleOperationMap.put("ROLE_ROOT_ADMIN", newRootAdminRole("ROLE_ROOT_ADMIN")); roleOperationMap.put("ROLE_ORDER_ADMIN", newOrderAdminRole("ROLE_ORDER_ADMIN")); roleOperationMap.put("ROLE_NORMAL", newNormalRole("ROLE_NORMAL") );}
publicstaticRoleOperation getOp( String roleName ) {returnroleOperationMap.get( roleName ); }}Copy the code


Next, with the factory above, the business code call is also a line of code, and the if/else is also eliminated:

PublicclassJudgeRole {publicString judge(String roleName) { Before theif/elseDidn't also!returnRoleFactory.getOp(roleName).op(); }}Copy the code


In this way, it is easy to extend the condition later by adding new code without touching the old business code, which is very much in line with the “open closed principle”.