抽象為類或者工廠
對(duì)于習(xí)慣于做面向?qū)ο笤O(shè)計(jì)的人來說,可能這意味著將復(fù)雜邏輯運(yùn)算打散并分布到不同的類里面:
switch (json.result) { case "ok": var factory = commandFactories.getFactory(json.command); var command = factory.buildCommand(json); command.execute(); break; }
這看起來不錯(cuò),至少分支變短了,代碼變得容易閱讀了。這個(gè) switch case 只管狀態(tài)碼分支,對(duì)于 “ok” 這個(gè)狀態(tài)碼具體怎么處理,那是其他類管的事情。 getFactory 里面可能有一組分支,專注于創(chuàng)建這條指令應(yīng)該選擇哪一個(gè)工廠的選擇。同時(shí) buildCommand 可能又有另外一些瑣碎的分支,決定如何構(gòu)建這條指令。
這樣做的好處是,分支之間的嵌套關(guān)系解除了,每一個(gè)分支只要在自己的上下文中保持正確就可以了。舉個(gè)例子來說, getFactory 現(xiàn)在是一個(gè)具名函數(shù),因此這個(gè)函數(shù)內(nèi)的分支只要實(shí)現(xiàn) getFactory 這個(gè)名字暗示的契約就可以了,無(wú)需關(guān)注實(shí)際調(diào)用 getFactory 的上下文。
抽象為模式匹配
另外一種做法,就是把這種復(fù)雜邏輯運(yùn)算轉(zhuǎn)述為模式匹配:
Network.listen({ "result": "ok", "command": "message", "content": { "from": "", "content": "kicked" } }, function(json) { /* disconnect */ });
Network.listen([{ "result": "ok", "command": "message", "content": { "type": "sysmsg" } }, { "result": "ok", "command": "systemmessage" }], function(json) { /* render system message */ });
Network.listen({ "result": "ok", "command": "message", "content": { "from$ne": "", "type$ne": "sysmsg" } }, func tion(json) { /* render chat message */ });
現(xiàn)在這樣子是不是清晰多了?第一種情況,是被踢下線,必須匹配指定的 from 和 content 值。第二種情況,是顯示系統(tǒng)消息,由于系統(tǒng)消息在兩個(gè)版本的協(xié)議中略有不同,所以我們要捕捉兩種不同的 JSON ,匹配任意一個(gè)都算是命中。第三種情況,是顯示聊天消息,由于在老版本協(xié)議中系統(tǒng)消息和踢下線指令都屬于特殊的聊天消息,為了兼容老版本協(xié)議,這兩種情況要從顯示聊天消息中排除出去,所以就使用了 “$ne” (表示 not equal )這樣的后綴進(jìn)行匹配。
由于 listen 方法是上下文無(wú)關(guān)的,每一個(gè) listen 都獨(dú)立聲明自己匹配什么樣的 JSON ,因此不存在任何隱含邏輯。例如說,要捕捉聊天消息,就必須顯式聲明排除 from == “” 以及 type == “sysmsg” 這兩種情況,這不需要由上下文的 if else 推斷得出。
使用模式匹配,可以大大提高代碼的可讀性和可維護(hù)性。由于我們要捕捉的是 JSON ,所以我們就使用 JSON 來描述每一個(gè)分支要捕捉什么,這比一個(gè)長(zhǎng)長(zhǎng)的邏輯運(yùn)算表達(dá)式要清晰多了。同時(shí)在這個(gè) JSON 上的每一處修改都是獨(dú)立的,修改一個(gè)條件并不影響其他條件。
本文鏈接:http://m.95time.cn/tech/web/2010/8085.asp
出處:百度泛用戶體驗(yàn)
責(zé)任編輯:bluehearts
上一頁(yè) 從if else到switch case再到抽象 [2] 下一頁(yè)
◎進(jìn)入論壇網(wǎng)頁(yè)制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評(píng)論。
|