多個if/else時,替代方案3個案例講解

一般來說我們正常的後臺管理系統都有所謂的角色的概念,不同管理員權限不一樣,
能夠行使的操作也不一樣,比如:
系統管理員( ROLE_ROOT_ADMIN):有 A操作權限
訂單管理員( ROLE_ORDER_ADMIN):有 B操作權限
普通用戶( ROLE_NORMAL):有 C操作權限

傳統的判斷方法是一串的if else 代碼臃腫

傳統方式的if else判斷

package com.ruoyi.web.controller.platform;

import com.ruoyi.web.controller.platform.IfelseEnum.JudgeRole;
import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;
import com.ruoyi.web.controller.platform.IfelseFactory.RootAdminRole;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ReplaceIfelse.class)
public class ReplaceIfelse {
    private final static Logger logger = LoggerFactory.getLogger(ReplaceIfelse.class);

    /**
     * 傳統方法
     * @param roleName
     * @return
     */
    public String judge(String roleName){
        String result="";
        if(roleName.equals("ROLE_ROOT_ADMIN")){
            result ="ROLE_ROOT_ADMIN"+"has AAA permission";
        }else if (roleName.equals("ROLE_ORDER_ADMIN")){
            result ="ROLE_ORDER_ADMIN"+"has BBB permission";
        }else if (roleName.equals("ROLE_NORMAL")){
            result ="ROLE_NORMAL"+"has CCC permission";
        }else {
            result ="XXX";
        }
        return result;
    }
}

枚舉方式替代if else

package com.ruoyi.web.controller.platform.IfelseEnum;

import org.springframework.stereotype.Service;

/**
 * 我們將不同角色的情況全部交由枚舉類來做,定義一個不同角色有不同權限的枚舉類
 */
@Service
public enum RoleEnum implements RoleOperation {

    ROLE_ROOT_ADMIN {
        @Override
        public String op() {
            return "ROLE_ROOT_ADMIN" + "has AAA permission" ;
        }
    },
    ROLE_ORDER_ADMIN {
        @Override
        public String op() {
            return "ROLE_ORDER_ADMIN" + "has BBB permission" ;
        }
    },
    ROLE_NORMAL {
        @Override
        public String op() {
            return "ROLE_NORMAL" + "has CCC permission" ;
        }
    }
}

工廠方式替代 if else

系統管理員

package com.ruoyi.web.controller.platform.IfelseFactory;

import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;
import org.springframework.stereotype.Service;

/**
 * 系統管理員(有A操作權限)
 */
@Service
public class RootAdminRole implements RoleOperation {

    private String roleName;

    public RootAdminRole(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String op() {
        return roleName + "has AAA permission" ;
    }
}

訂單管理員

package com.ruoyi.web.controller.platform.IfelseFactory;

import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;
import org.springframework.stereotype.Service;
/**
 * 訂單管理員(有B操作權限)
 */
@Service
public class OrderAdminRole implements RoleOperation {


    private String roleName;

    public OrderAdminRole(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String op() {
        return roleName+"has BBB permission";
    }

}

普通管理員

package com.ruoyi.web.controller.platform.IfelseFactory;

import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;
import org.springframework.stereotype.Service;
/**
 * 普通管理員(有C操作權限)
 */
@Service
public class NormalRole implements RoleOperation {
    private String roleName;

    public NormalRole(String roleName) {
        this.roleName = roleName;
    }
    @Override
    public String op() {
        return roleName+"has CCC permission";
    }
}

工廠類

package com.ruoyi.web.controller.platform.IfelseFactory;

import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;

import java.util.HashMap;
import java.util.Map;

/**
 * 不同分支做不同的事情,很明顯就提供了使用工廠模式的契機,我們只需要將不同情況單獨定義好,然後去工廠類裏面聚合即可。
 * 寫一個工廠類 RoleFactory對上面不同角色進行聚合
 */
public class RoleFactory {
    static Map<String, RoleOperation> roleOperationMap=new HashMap<String, RoleOperation>();
    // 在靜態塊中先把初始化工作全部做完
    static {
        roleOperationMap.put("ROLE_ROOT_ADMIN",new RootAdminRole("ROLE_ROOT_ADMIN"));
        roleOperationMap.put("ROLE_ORDER_ADMIN",new OrderAdminRole("ROLE_ORDER_ADMIN"));
        roleOperationMap.put("ROLE_NORMAL",new NormalRole("ROLE_NORMAL"));
    }

    public static RoleOperation getOp(String roleNeme){
        return roleOperationMap.get(roleNeme);
    }
}

策略方式替代 if else

package com.ruoyi.web.controller.platform.IfelseStrategy;

import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;

/**
 * 在上面工廠模式代碼的基礎上,按照策略模式的指導思想,我們也來創建一個所謂的策略上下文類,這裏命名爲 RoleContext
 */
public class RoleContext {
    // 可更換的策略,傳入不同的策略對象,業務即相應變化
    private RoleOperation operation;

    public RoleContext(RoleOperation operation) {
        this.operation = operation;
    }

    public String execute(){
        return operation.op();
    }
}

公共方法

package com.ruoyi.web.controller.platform.IfelseEnum;

public interface RoleOperation {
    // 表示某個角色可以做哪些op操作
    String op();
}

package com.ruoyi.web.controller.platform.IfelseEnum;

import com.ruoyi.web.controller.platform.IfelseFactory.RoleFactory;
import com.ruoyi.web.controller.platform.IfelseStrategy.RoleContext;

/**
 * 判斷Judge角色
 */
public class JudgeRole {
    /**
     * 枚舉模式消除if else
     * 而且這樣一來,以後假如我想擴充條件,只需要去枚舉類中加代碼即可,而不是去改以前的代碼,這豈不很穩!
     * @param roleName
     * @return
     */
    public String judgeEnum (String roleName){
        String op = RoleEnum.valueOf(roleName).op();
        return op;
    }

    /**
     * 工廠模式消除if else
     * 接下來藉助上面這個工廠,業務代碼調用也只需一行代碼, if/else同樣被消除了:
     * @param roleName
     * @return
     */
    public String judgeFactory(String roleName){
        String op = RoleFactory.getOp(roleName).op();
        return op;
    }

    /**
     * 策略模式消除if else
     * @return
     */
    public String judgeStrategy(RoleOperation roleOperation){
        RoleContext roleContext=new RoleContext(roleOperation);
        return roleContext.execute();
    }


}

測試上述3種方式

package com.ruoyi.web.controller.platform;

import com.ruoyi.web.controller.platform.IfelseEnum.JudgeRole;
import com.ruoyi.web.controller.platform.IfelseEnum.RoleOperation;
import com.ruoyi.web.controller.platform.IfelseFactory.RootAdminRole;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ReplaceIfelse.class)
public class ReplaceIfelse {
    private final static Logger logger = LoggerFactory.getLogger(ReplaceIfelse.class);

    @Test
    public void judgeIfelse(){
        JudgeRole judgeRole=new JudgeRole();
        String roleRootAdmin = judgeRole.judgeEnum("ROLE_ROOT_ADMIN");
        String roleOrderAdmin = judgeRole.judgeEnum("ROLE_ORDER_ADMIN");
        String roleNormal = judgeRole.judgeEnum("ROLE_NORMAL");
        logger.info(">>>>枚舉方式獲取角色權限:{}>>>>",roleRootAdmin +"___"+ roleOrderAdmin+"___"+roleNormal);
        String roleRootAdmin1 = judgeRole.judgeFactory("ROLE_ROOT_ADMIN");
        String roleOrderAdmin1 = judgeRole.judgeFactory("ROLE_ORDER_ADMIN");
        String roleNormal1 = judgeRole.judgeFactory("ROLE_NORMAL");
        logger.info(">>>>工廠方式獲取角色權限:{}>>>>",roleRootAdmin1 +"___"+ roleOrderAdmin1+"___"+roleNormal1);
        String roleRootAdmin2 = judgeRole.judgeStrategy(new RootAdminRole("ROLE_ROOT_ADMIN"));
        String roleOrderAdmin2 = judgeRole.judgeStrategy(new RootAdminRole("ROLE_ORDER_ADMIN"));
        String roleNormal2 = judgeRole.judgeStrategy(new RootAdminRole("ROLE_NORMAL"));
        logger.info(">>>>策略方式獲取角色權限:{}>>>>",roleRootAdmin1 +"___"+ roleOrderAdmin1+"___"+roleNormal1);
    }
}

結果

>>>>枚舉方式獲取角色權限:ROLE_ROOT_ADMINhas AAA permission___ROLE_ORDER_ADMINhas BBB permission___ROLE_NORMALhas CCC permission>>>>
>>>>工廠方式獲取角色權限:ROLE_ROOT_ADMINhas AAA permission___ROLE_ORDER_ADMINhas BBB permission___ROLE_NORMALhas CCC permission>>>>
>>>>策略方式獲取角色權限:ROLE_ROOT_ADMINhas AAA permission___ROLE_ORDER_ADMINhas BBB permission___ROLE_NORMALhas CCC permission>>>>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章