摘要:如果把設計模式當做一門語言的話,我覺得組合模式就是里面的數組,或者更確切的說,應該算是一棵樹。給向上的綁定向上的執行程序可以看出,使用組合模式命令模式可以完美的打出個兩個王的終極炸彈。將同類操作同目的操作放在一組。
如果把設計模式當做一門語言的話,我覺得組合模式就是里面的數組,或者更確切的說,應該算是一棵樹。 樹的枝干就是其他模式的使用,比如命令模式,代理模式,單例模式等等??偟膩碚f,組合模式在這里就相當于一個容器,但也并非僅僅是個容器(不然,我還給他冠名"模式").
組合模式+命令模式上篇的命令模式大家應該可以了解到,一個命令和命令執行者的相關系數為 zero . 所以你對命令的執行者做什么都不要緊,但是他的接口必須保持一致。 而這個特性映射出一個道理,就是既然我可以do anything, 意味著我可以在執行者上面加上其他的執行者.
are u ok?
恩恩,I"m fine, fuck u.
當然,這時候這個執行者就不叫做命令,而應該改口叫做宏。來,和上一篇一樣,說球的問題。
//當點擊一個球后,讓球往上走,再往右走 var setCommand = function(ele, command) { ele.onclick = function() { command.exe(); } } var locat = (function() { //執行事件類 var ball = getEle("#pic"), style = ball.style; //緩存style var move = function(direct) { return function() { var dir; switch (direct) { case "bottom": dir = parseInt(getLocat(ball).top) || 0; style.top = `${dir+10}px`; break; case "right": dir = parseInt(getLocat(ball).left) || 0; style.left = `${dir+10}px`; break; default: dir = parseInt(getLocat(ball)[direct]) || 0; style[direct] = `${dir-10}px`; } } } return { moveUp: move("top"), moveDown: move("bottom"), moveLeft: move("left"), moveRight: move("right") } })(); //封裝命令 var moveUR = (function(){ var exe = function(){ locat.moveUp(); locat.moveRight(); } return { //封裝命令 exe } })(); setCommand(getEle("leftUpBtn"), moveUR); //綁定執行效果的程序
可以看出,上面的代碼可以完成基本任務。但是,如果某一天你的leader要求,讓小球 上->右->下->左 進行一個循環回到原始的位置,恐怕你的反應不是很強烈。就是在moveUR里面再加些東西唄。呵呵,來,你leader又說了。在上->右->下的時候轉個圈然后->左.(Ps: 轉個毛線啊~~~~), 表示聽到這里,想想某天你的leader抽風了,又換一個實現方式。 我想,你年都過不好~。
所以,為了讓你早些回家,早點見爹媽,早點領年終獎,早點買春運火車票~
我相信,命令模式是你不二之選.
我們使用命令模式重構一下.
//上面部分不動,只將下面部分改寫 //命令集合 var command = function(){ var lists = []; return { add(command){ lists.push(command); }, exe(){ for(var i = 0,command;command = lists[i++];){ command.exe(); } } } } //封裝命令 var moveUp = (function(){ var exe = function(){ locat.moveUp(); } return { exe } })(); var moveLeft = (function(){ var exe = function(){ locat.moveLeft(); } return{ exe } })(); var moveGroup1 = command(); //得到一個命令集 moveGroup1.add(moveUp); //添加向上的命令 moveGroup1.add(moveLeft); //。。。。 setCommand(getEle("leftUpBtn"), moveGroup1); //給向上的button,綁定向上的執行程序
可以看出,使用組合模式+命令模式可以完美的打出4個2+兩個王的終極炸彈。 你可以隨機的添加你想要的效果,但是前提還是必須保證有一致的接口內容。
現在可以看出組合模式的好處了吧。 想想,這個模式的特點--隊列。沒錯,組合模式會創建一棵樹,而這棵樹的枝干全部是有你來添加,你可以讓他變成百年梧桐,也可以讓他變成行道樹,而且調用的方式極其簡單,使用一個接口,這棵樹會把你的命令通過莖,一個接一個的輸送過去。
talk is cheap, show u code
var moveUP = (function(){ var exe = funciton(){ conosle.log("moveUP"); } return { exe } })(); var moveLeft = (function(){ var exe = funciton(){ conosle.log("moveLeft"); } return { exe } })(); var moveBottom = (function(){ var exe = funciton(){ conosle.log("moveBottom"); } return { exe } })(); var moveRight = (function(){ var exe = funciton(){ conosle.log("moveRight"); } return { exe } })(); //加一點難度,對命令進行分組 var moveGrop1 = command(); moveGrop1.add(moveUp); //moveUp moveGrop1.add(moveLeft); //moveLeft var moveGrop2 = command(); moveGrop2.add(moveBottom); //moveBottom moveGrop2.add(moveRight); //moveRight var moveGrop3 = command(); moveGrop3.add(moveBottom); //moveBottom moveGrop3.add(moveBottom); //moveBottom var moveGrop = command(); moveGrop.add(moveGrop1); moveGrop.add(moveGrop2); moveGrop.add(moveGrop3); moveGrop.exe(); //接下來會按上面的順序一個一個的運行。
可以看出,組合模式最大的一個特點就是分組操作。將同類操作(同目的操作)放在一組。 就像做一個gif了,一個幀+一個幀+一個幀... 比如,我可以蹲下來,然后起跳。 我又可以蹲下來,然后站立,走路。 就可以把一個片段,一個片段組合成你最想要的效果(懷念高中時候沒有好好學習排列組合 :(] 而且重用性也是杠杠的。
可以看出,上面的add這樣寫好蠢。。。 為了滿足裝逼的需求,決定優化一下。
//命令集合 var command = function(){ var lists = []; return { add(){ for(var i = 0,command; command = arguments[i++];){ lists.push(command); } console.log(lists); }, exe(){ for(var i = 0,command;command = lists[i++];){ command.exe(); } } } } //添加命令 var moveGrop1 = command(); moveGrop1.add(moveUp,moveLeft); //moveUp,moveLeft var moveGrop2 = command(); moveGrop2.add(moveBottom,moveRight); //moveBottom,moveRight var moveGrop3 = command(); moveGrop3.add(moveBottom,moveBottom); //moveBottom,moveBottom var moveGrop = command(); moveGrop.add(moveGrop1,moveGrop2,moveGrop3); moveGrop.exe(); //接下來會按上面的順序一個一個的運行。
干凈,漂亮,美美的.
但是,世上沒有完美的代碼,命令模式來擴展宏命令,這個是他的劍,也是他的死穴。 這樣會造成,你的根節點和子節點(不可擴展的節點)之間層次的不分明。所以,一般,我們會在子節點上面加上說明,防止意外添加而導致的出錯,不然,bug一出,春運票你也別想買了。
舉個栗子:
var moveGrop = command(); moveGrop1.add(moveUP); moveUP.add(moveLeft);
雖然看上去這段代碼很蠢,但事實上,我確實踩過===我也很蠢xxx... 所以,這里希望警戒大家,希望把這個錯誤的發生率降到 0.000000001%.吧。
當然,一個藝術家,往往會給自己留一手。
var moveUp = (function(){ var exe = funciton(){ conosle.log("moveUp"); } var add = function(){ throw "你很蠢,不,你真的很蠢." } return { exe,add } })();
這樣,萬一哪天,真的蠢了,好歹也知道自己怎么蠢的。自己知道自己蠢就可以了,記得代碼寫完后,把這段給刪了(紅臉).
組合模式注意tips組合模式雖然很strong.但是有些概念性問題,我們還是必須分清楚.
組合模式里,根節點和子節點并不是父子關系。即,他們之間,并不存在繼承關系。只是他們接口名一致而已。
字節點對象必須是同類的,這里說說的同類是指完成同一個目的相互協作的。如果將另外一個組的子節點插進來,造成的結果就是over.
盡量給根節點和子節點取望文生義的名字,后面最好標注他們的屬性(根,子).
組合模式的其他用處這個用處出自于< AlloyTeam的曾探>.(一枚我超級崇拜的大神)
組合模式的特點是子對象地位平等,特別符合我們所說的文件掃描功能。 即,文件掃描只需要知道你的文件名,以及所處的位置即可。
這里我們可以把文件比作子節點,文件夾比作父節點.
var folder = function(name){ return { name, //文件夾名 files:[], add(){ for(var i = 0,file;file = arguments[i++];){ file.parent = this; this.files.push(file); } }, scan(){ //掃描文件 for(var file of this.files){ console.log(file.name); } }, remove(){ if(!this.parent){ alert("該文件是更目錄,不能刪除!"); return; } for(var files = this.parent.files,len = files.length-1;len>=0;len--){ //倒敘遍歷文件夾 var file = files[len]; if(file === this){ files.splice(len,1); //刪除文件 break; } } } } } var file = function(name){ return { name, scan(){ console.log(`this is ${name}`); }, remove(){ if(!this.parent){ alert("該文件是更目錄,不能刪除!"); return; } for(var files = this.parent.files,len = files.length-1;len>=0;len--){ //倒敘遍歷文件夾 var file = files[len]; if(file === this){ files.splice(len,1); //刪除文件 break; } } }, add(){ throw "你很蠢,不,你真的很蠢!" } } } var jimmyFolder = folder("jimmy"); var avi1 = file("小澤瑪利亞.avi"); var avi2 = file("上野真知子.avi"); jimmyFolder.add(avi1,avi2); jimmyFolder.scan(); //小澤瑪利亞.avi , 上野真知子.avi avi1.remove(); jimmyFolder.scan(); //上野真知子.avis
恩,get(工口).
當然,這只是一個比較簡單的例子,隨著你對根節點的不斷操作,后面遇到的問題,肯定會凸顯出來,要知道,這樣,組合模式里面的節點保存是非常耗內存的,所以這個模式肯定還有很多可以優化的地方.
最后,還是那句話,不要為了模式而模式。 對于模式而言還是希望先寫,后添加。
ending~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78505.html
摘要:到十二月份,公司開始第二波裁員,我決定主動拿賠償走人。加一個小插曲上面的題是餓了嗎面試問到的。想去的公司沒有面試好,不要氣餒,繼續加油準備。避免打擊自信心。 回顧一下自己這段時間的經歷,九月份的時候,公司通知了裁員,我匆匆忙忙地出去面了幾家,但最終都沒有拿到offer,我感覺今年的寒冬有點冷。到十二月份,公司開始第二波裁員,我決定主動拿賠償走人。后續的面試過程我做了一些準備,基本都能走...
摘要:二提高代碼語義性針對上述三個案例,用更加語義化的方式來呈現代碼語義化變量類型判斷我覺得不需要太多的解釋,對比顯得清新多了吧。 語義化這個詞在 HTML 中用的比較多,即根據內容的結構化選擇合適的標簽。其作用不容小覷: 賦予標簽含義,讓代碼結構更加清晰,雖然我們可以在標簽上添加 class 來標識,但這種通過屬性來表示本體的形式會顯得不夠直接,而且在一定程度上也有冗余。 優化搜索引擎...
摘要:調度系統,支持不同渲染優先級,對進行調度。調度帶來的限制調度系統也存在兩個問題。調度系統能力有限,只能在瀏覽器提供的能力范圍內進行調度,而無法影響比如的渲染回收周期。精讀關于調度系統的剖析,可以讀深入剖析這篇文章,感謝我們團隊的淡蒼提供。 1. 引言 這次介紹的文章是 scheduling-in-react,簡單來說就是 React 的調度系統,為了得到更順滑的用戶體驗。 畢竟前端做到...
摘要:如問到是否使用某框架,實際是是問該框架的使用場景,有什么特點,和同類可框架對比一系列的問題。這兩個方向的區分點在于工作方向的側重點不同。 [TOC] 這是一份來自嗶哩嗶哩的Java面試Java面試 32個核心必考點完全解析(完) 課程預習 1.1 課程內容分為三個模塊 基礎模塊: 技術崗位與面試 計算機基礎 JVM原理 多線程 設計模式 數據結構與算法 應用模塊: 常用工具集 ...
閱讀 2033·2021-09-30 09:47
閱讀 708·2021-09-22 15:43
閱讀 1987·2019-08-30 15:52
閱讀 2439·2019-08-30 15:52
閱讀 2549·2019-08-30 15:44
閱讀 912·2019-08-30 11:10
閱讀 3375·2019-08-29 16:21
閱讀 3301·2019-08-29 12:19