答应我,别再if/else走天下了可以吗
?哎,曾幾何時(shí)?
想當(dāng)年,其實(shí)我也特別鐘情于 if/else連環(huán)寫(xiě)法,上來(lái)就是一頓SAO操作,比如舉個(gè)好理解的簡(jiǎn)單栗子:
一般來(lái)說(shuō)我們正常的后臺(tái)管理系統(tǒng)都有所謂的角色的概念,不同管理員權(quán)限不一樣,能夠行使的操作也不一樣,比如:
系統(tǒng)管理員(?ROLE_ROOT_ADMIN):有?A操作權(quán)限
訂單管理員(?ROLE_ORDER_ADMIN):有?B操作權(quán)限
普通用戶(?ROLE_NORMAL):有?C操作權(quán)限
比如一個(gè)用戶進(jìn)來(lái),我們需要根據(jù)不同用戶的角色來(lái)判斷其有哪些行為,這時(shí)候SAO代碼出現(xiàn)了:
public class JudgeRole {public String judge( String roleName ) {String result = "";if (roleName.equals("ROLE_ROOT_ADMIN")) { // 系統(tǒng)管理員有A權(quán)限r(nóng)esult = "ROLE_ROOT_ADMIN: " + "has AAA permission";} else if ( roleName.equals("ROLE_ORDER_ADMIN") ) { // 訂單管理員有B權(quán)限r(nóng)esult = "ROLE_ORDER_ADMIN: " + "has BBB permission";} else if ( roleName.equals("ROLE_NORMAL") ) { // 普通用戶有C權(quán)限r(nóng)esult = "ROLE_NORMAL: " + "has CCC permission";} else {result = "XXX";}return result;} }這樣當(dāng)系統(tǒng)里有幾十個(gè)角色時(shí),那幾十個(gè) if/else嵌套可以說(shuō)是非常酸爽了…… 這樣一來(lái)非常不優(yōu)雅,別人閱讀起來(lái)很費(fèi)勁;二來(lái)則是以后如果再?gòu)?fù)雜一點(diǎn),或者想要再加條件的話不好擴(kuò)展;而且代碼一改,以前的老功能肯定還得重測(cè),豈不瘋了……
所以,如果在不看下文的情況下,你一般會(huì)如何去對(duì)付這些令人頭痛的if/else語(yǔ)句呢?
當(dāng)然有人會(huì)說(shuō)用 switch/case來(lái)寫(xiě)是否會(huì)優(yōu)雅一些呢?答案是:毛區(qū)別都沒(méi)有!
接下來(lái)簡(jiǎn)單講幾種改進(jìn)方式,別再 if/else走天下了
?有枚舉為啥不用?
什么角色能干什么事,這很明顯有一個(gè)對(duì)應(yīng)關(guān)系,所以學(xué)過(guò)的枚舉為啥不用呢?
首先定義一個(gè)公用接口 RoleOperation,表示不同角色所能做的操作:
public interface RoleOperation {String op(); // 表示某個(gè)角色可以做哪些op操作 }接下來(lái)我們將不同角色的情況全部交由枚舉類(lèi)來(lái)做,定義一個(gè)不同角色有不同權(quán)限的枚舉類(lèi) RoleEnum:
public enum RoleEnum implements RoleOperation {// 系統(tǒng)管理員(有A操作權(quán)限)ROLE_ROOT_ADMIN {@Overridepublic String op() {return "ROLE_ROOT_ADMIN:" + " has AAA permission";}},// 訂單管理員(有B操作權(quán)限)ROLE_ORDER_ADMIN {@Overridepublic String op() {return "ROLE_ORDER_ADMIN:" + " has BBB permission";}},// 普通用戶(有C操作權(quán)限)ROLE_NORMAL {@Overridepublic String op() {return "ROLE_NORMAL:" + " has CCC permission";}}; }接下來(lái)調(diào)用就變得異常簡(jiǎn)單了,一行代碼就行了, if/else也灰飛煙滅了:
public class JudgeRole {public String judge( String roleName ) {// 一行代碼搞定!之前的if/else沒(méi)了!return RoleEnum.valueOf(roleName).op();} }而且這樣一來(lái),以后假如我想擴(kuò)充條件,只需要去枚舉類(lèi)中加代碼即可,而不是去改以前的代碼,這豈不很穩(wěn)!
除了用枚舉來(lái)消除 if/else,工廠模式也可以實(shí)現(xiàn)
?有工廠模式為啥不用?
不同分支做不同的事情,很明顯就提供了使用工廠模式的契機(jī),我們只需要將不同情況單獨(dú)定義好,然后去工廠類(lèi)里面聚合即可。
首先,針對(duì)不同的角色,單獨(dú)定義其業(yè)務(wù)類(lèi):
// 系統(tǒng)管理員(有A操作權(quán)限) public class RootAdminRole implements RoleOperation {private String roleName;public RootAdminRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has AAA permission";} } // 訂單管理員(有B操作權(quán)限) public class OrderAdminRole implements RoleOperation {private String roleName;public OrderAdminRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has BBB permission";} } // 普通用戶(有C操作權(quán)限) public class NormalRole implements RoleOperation {private String roleName;public NormalRole( String roleName ) {this.roleName = roleName;}@Overridepublic String op() {return roleName + " has CCC permission";} }接下來(lái)再寫(xiě)一個(gè)工廠類(lèi) RoleFactory對(duì)上面不同角色進(jìn)行聚合:
public class RoleFactory {static Map<String, RoleOperation> roleOperationMap = new HashMap<>();// 在靜態(tài)塊中先把初始化工作全部做完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 roleName ) {return roleOperationMap.get( roleName );} }接下來(lái)借助上面這個(gè)工廠,業(yè)務(wù)代碼調(diào)用也只需一行代碼, if/else同樣被消除了:
public class JudgeRole {public String judge( String roleName ) {// 一行代碼搞定!之前的 if/else也沒(méi)了!return RoleFactory.getOp(roleName).op();} }這樣的話以后想擴(kuò)展條件也很容易,只需要增加新代碼,而不需要?jiǎng)右郧暗臉I(yè)務(wù)代碼,非常符合“開(kāi)閉原則”。
來(lái),我們接著來(lái),除了工廠模式,策略模式也不妨試一試
?有策略模式為啥不用?
策略模式和工廠模式寫(xiě)起來(lái)其實(shí)區(qū)別也不大!
在上面工廠模式代碼的基礎(chǔ)上,按照策略模式的指導(dǎo)思想,我們也來(lái)創(chuàng)建一個(gè)所謂的策略上下文類(lèi),這里命名為 RoleContext:
public class RoleContext {// 可更換的策略,傳入不同的策略對(duì)象,業(yè)務(wù)即相應(yīng)變化private RoleOperation operation; public RoleContext( RoleOperation operation ) {this.operation = operation;}public String execute() {return operation.op();} }很明顯上面?zhèn)魅氲膮?shù) operation就是表示不同的“策略”。我們?cè)跇I(yè)務(wù)代碼里傳入不同的角色,即可得到不同的操作結(jié)果:
public class JudgeRole {public String judge( RoleOperation roleOperation ) {RoleContext roleContext = new RoleContext( roleOperation );return roleContext.execute();} } public static void main( String[] args ) {JudgeRole judgeRole = new JudgeRole();String result1 = judgeRole.judge(new RootAdminRole("ROLE_ROOT_ADMIN"));System.out.println( result1 );String result2 = judgeRole.judge(new OrderAdminRole("ROLE_ORDER_ADMIN"));System.out.println( result2 );String result3 = judgeRole.judge(new NormalRole("ROLE_NORMAL"));System.out.println( result3 ); }?共? ?勉?
好了,先講到這里吧,本文僅僅是拋磚引玉,使用了一個(gè)極其簡(jiǎn)單的示例來(lái)打了個(gè)樣,然而其思想可以廣泛地應(yīng)用于實(shí)際復(fù)雜的業(yè)務(wù)和場(chǎng)景,思想真的很重要!寫(xiě)代碼前還是得多思考一番,考慮是否有更具可擴(kuò)展性的寫(xiě)法!
后? ?記
若有錯(cuò)誤或者不當(dāng)之處,可在本公眾號(hào)內(nèi)反饋,一起學(xué)習(xí)交流!
The End來(lái)和小伙伴們一起向上生長(zhǎng)呀!掃描下方二維碼,添加小詹微信,可領(lǐng)取千元大禮包并申請(qǐng)加入 Python 學(xué)習(xí)交流群,群內(nèi)僅供學(xué)術(shù)交流,日常互動(dòng),如果是想發(fā)推文、廣告、砍價(jià)小程序的敬請(qǐng)繞道!一定記得備注「交流學(xué)習(xí)」,我會(huì)盡快通過(guò)好友申請(qǐng)哦!????長(zhǎng)按識(shí)別,添加微信(添加人數(shù)較多,請(qǐng)耐心等待)????長(zhǎng)按識(shí)別,關(guān)注小詹(掃碼回復(fù) 1024 領(lǐng)取程序員大禮包) 與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的答应我,别再if/else走天下了可以吗的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 你以为文言编程只是闹着玩?三个月后,人家
- 下一篇: 人工智能到底是个啥,这几本书讲得透透得!