<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                >[success] # 設計模式 -- 命令模式(菜鳥教程中代理模式總結) ~~~ 1.定義: 1.1將請求以命令的形式包裹在對象中,這個對象傳遞給調用者 1.2.調用者尋找可以處理該命令的合適對象,這個對象會處理傳過來命令 2.主要解決:行為請求者與行為實現者通常是一種緊耦合的關系,為了消除這種耦合關系 3.何時使用:命令執行過程較為復雜且可能存在變化,需要對執行命令動作本身進行額外操作, 此時可以考慮使用命令模式 4.如何解決:通過調用者調用接受者執行命令,順序:調用者→接受者→命令。 5.關鍵代碼:定義三個角色:1、received 真正的命令執行對象 2、Command(命令) 3、invoker 使用命令對象的入口 ~~~ * 解釋 ~~~ 1.站在主要解決上舉個例子:比如電視它具有開和關的功能,用代碼來表示的話就是一個'電視類'有兩個方法'開電視', '關電視'。一般執行的時候'電視.開電視',對應上面說的'主要解決來講'開電視這個行為和開電視這個實現 都是電視來做的兩者是在一起 2.站在定義上:這時候遙控器出現了,'開/關電視'的行為請求。可以看做兩個命令,并且將這兩個命令單獨寫成對象 現在就多了兩個對象'開電視' 和'關電視'他們是一組命令,多了個'遙控器'可以調用這些命令,并且把這些命令 給了電視,電視依舊還是有'開電視', '關電視'的方法,不過不是直接請求調用而是遙控器間接調用了 ~~~ >[danger] ##### 優缺點 * 優點 ~~~ 1.Invoker(調用者)的存在使命令執行之前有了更多的設計空間(日志記錄、命令回滾、拒絕執行命令、命令隊列等) 2.對命令進行封裝,使命令易于擴展和修改 3.命令發出者和接受者解耦,使發出者不需要知道命令的具體執行過程即可執行 ~~~ * 缺點 ~~~ 1、使用命令模式可能會導致某些系統有過多的具體命令類。 ~~~ >[danger]使用場景 ~~~ 認為是命令的地方都可以使用命令模式,比如: 1、GUI 中每一個按鈕都是一條命令。 2、模擬 CMD。 ~~~ >[danger] ##### 簡單的理解 ~~~ 1.當我們在定義類的時候,往往將對象的行為和動作進行統一,看做一個整體,對象去調用自己的行為, 這就需要調用者要知道對應的'行為' 屬于哪一個'對象',但是在像cmd 等輸入腳本命令行界面,我們往往 根本不需要知道指令是在具體那個位置封裝,而是直接發出輸入指令,系統會幫助我們將指令和對應調用 對象進行匹配,生活中為例去飯店吃飯也是一樣,我們只關心菜單上的菜,不會去必須要知道那個廚師 因為服務員會幫我們將菜單上的'指令' 和廚師進行匹配 2.命令模式依舊是遵循我們編程上的思想,依然需要定義某一類事物的具體行為和動作,比如'w廚師' 他會 做的每一道菜都是他的行為是屬于他的整體,但是也需要將每個廚師會的每一道菜在單獨抽離出來,這些 行為就是'指令' 形成個體,這些指令并不會自動觸發,所以他們需要接受他們的調用者是誰。但是在使用層面 我們只需要執行組合好的'指令即可',因為單獨的指令層已經幫我們將調用者和'指令'組合好了 ~~~ >[info] ## 延伸不錯的講解命令模式文章 [參考地址](https://cloud.tencent.com/developer/article/1056075) >[danger] ##### 文章一什么是命令模式圖解 ~~~ 1.假設現在有個請求處理,正常操作客戶端直接調用請求處理的類 ~~~ * 類似解釋中沒有遙控器的電視 ![](https://img.kancloud.cn/f9/a9/f9a9cf625c2b8e879afeabfa7faabc27_478x195.png) ~~~ 1.引入命令模式后客戶端的請求發送類和請求處理類之間增加一個Invoker類,再將請求發送類發送 的所有請求封裝成對象,然后讓Invoker(調用者)類去管理這些請求對象,并決定這些請求是否允許 執行、何時執行、按什么順序執行。 2.好處:由于在請求發送類和請求處理類之間增加了請求轉發者,因此這兩個類之間的藕合度就大大降低。 3.分析圖:'Infvoker (調用者) 遙控器','Command(命令)開機/關機','Receiver(接受者)就是電視類里面有開關機方法' ~~~ * 命令模式的類圖 ![](https://img.kancloud.cn/0e/83/0e830c047718098a4518fc28e583e614_887x407.png) >[danger] ##### 對命令模式的劃分 [命令模式](https://blog.csdn.net/weixin_42746530/article/details/90777275) * 文章中的類圖 ![](https://img.kancloud.cn/6e/3e/6e3eb834e3627b9807e4e12e107f3e5b_921x391.png) * 文章中的說明 ~~~ Client : 即請求發出者,通過調用Invoker方法發出請求。 Invoker : 請求的調用者,內部持有具體請求的引用。 ConcreteCommand :封裝的請求對象,內部持有Receiver對象。 Receiver:請求接受者,根據請求對象的指揮進行不同的反應。 ~~~ >[success] # 前端命令模式 * 一定要看一二條這思維邏輯轉換 ~~~ 1.傳統的我們想法就是一個'Receiver'接受者,你需要調用啥我就直接這個對象點他對應的方法 2.命令模式思想轉換,不在直接去調用這個'Receiver'接受者,我們通過分裝一些命令,這些命令 類ConcreteCommand 去間接的調用這些'Receiver'接受者。和策略模式處理方式很像,但是出發 點不同,可以參看命令和策略的區別 3.書中舉了一個例子,現在有個需求有十個按鈕,讓兩個人來寫,一個人負責按鈕的繪制工作, 一個人負責寫這個按鈕點擊后的具體行為封裝到對象中 4.根據命令模式分析這個需求,參照上面'文章一什么是命令模式圖解',可以發現'寫按鈕的一方是客戶端', 寫這些'按鈕事件功能的對應圖中的請求處理類',為了想讓他倆解耦畫按鈕的如果比寫邏輯的先完成, 我又不想讀你的'事件觸發的代碼'等你寫完后在加到和我按鈕關聯,這時候使用'命令模式'達到解耦 5.書上先說了命令模式的'場景': 有時候需要向某些對象發送請求,但是并不知道'請求的接收者是誰','也不知道被請 求的操作是什么', 此時希望用一種松耦合的方式來設計軟件,使得請求發送者和請求接 收者能夠消除彼此之間的耦合關系。 根據這個場景書中的得到的'理由': 點擊了按鈕之后,必須向某些'負責具體行為的對象發送請求','這些對象就是請求的接收者'。 但是目前并'不知道接收者是什么對象','也不知道 接收者究竟會做什么'。此時我們需要借助命令對象的幫助, 以便解開按鈕和負責具體行為對象之 間的耦合。 ~~~ >[danger] ##### 根據上面分析實現代碼 ~~~ 1.首先需要一個'Receiver' 請求的接受者,簡單的理解這里面有上面所有按鈕的'具體行為動作' 2.需要一個'ConcreteCommand ' 是每一個單獨指令,這些單獨指令對象中都有'Receiver'對象, 他們都會有一個共同的方法(在java 或者是ts中甚至es6我們會吧這個共同的方法定義在一個接口中) 3.需要一個'Invoker'請求的調用者,他將會具體調用某個指令對象(有點像代理模式,但區別是他的 調用方法不用像代理模式那樣需要和被代理對象實現名字一樣的方法) ~~~ * 代碼實現 ~~~ 1.下面代碼中的'Receiver' -- MenuBar 和 SubMenu 他們有所有按鈕的具體行為動作 2.'ConcreteCommand ' -- 'RefreshMenuBarCommand','AddSubMenuCommand ','DelSubMenuCommand ' 這些對象是將'Receiver' 中的每個具體行為拆分開來,他們都有一個特定,內部都有'Receiver' 也就是請求接受者的對象,有一個共同的方法'execute' 來調用這些'Receiver'中與之匹配的方法 3.'Invoker' -- 'setCommand' 也就是請求調用者,他們會接受'ConcreteCommand' 對象并且 調用他們 4.命令都有同一接口實現為什么這么做看'execute'方法 ~~~ ~~~ <html> <head> <meta charset="utf-8"> </head> <body> <button id="button1">點擊按鈕1</button> <button id="button2">點擊按鈕2</button> <button id="button3">點擊按鈕3</button> </body> <script> // 需求現在有個刷新菜單目錄,增加子菜單,刪除子菜單工 ,我們用命令模式實現 var button1 = document.getElementById('button1') var button2 = document.getElementById('button2') var button3 = document.getElementById('button3') // 首先有個received 真正的執行者 也就是這些功能對象集合,這里指的是上面所有按鈕的'具體行為動作' var MenuBar = { refresh:function(){ console.log('刷新目錄') } } var subMenu = { add:function(){ console.log('增加子菜單') }, del:function(){ console.log('刪除子菜單') } } // --------------------------command命令-------------------------------------- // 需要 有執行received 對象中方法的命令 command,命令的參數是要執行接受者Receiver // 一個命令對象對準一個Receiver對象的 方法,命令形式驅動這些對象方法 var RefershMenuBarCommand = function(received){ this.received = received } RefershMenuBarCommand.prototype.execute = function(){ this.received.refresh() } // 針對子菜單里面增加方法 var AddSubMenuCommand = function (receiver) { this.receiver = receiver } AddSubMenuCommand.prototype.execute = function(){ this.receiver.add() } var DeleteSubMenuCommand = function (receiver) { this.receiver = receiver } DeleteSubMenuCommand.prototype.execute = function(){ this.receiver.del() } // --------------------------'Invoker'請求的調用者,他將會具體調用某個指令對象-------------------------------------- // Invoker調用者 將 指令command 和 received 進行匹配 var setCommand = function(button,command){ button.onclick = function(){ command.execute() } } // ----------------使用------------------- // 使用 將received 這些真正的執行也就是這些功能集合的對象 // 和指令進行匹配調用 var refershMenuBarCommand = new RefershMenuBarCommand(MenuBar) // 再將這些匹配好的和invoke調用者,來執行 setCommand(button1,refershMenuBarCommand) </script> </html> ~~~ >[danger] ##### es6 更清晰的寫法 ~~~ // 需求現在有個刷新菜單目錄,增加子菜單,刪除子菜單工 ,我們用命令模式實現 var button1 = document.getElementById('button1') var button2 = document.getElementById('button2') var button3 = document.getElementById('button3') // 最開始 所有的方法都屬于自己對象的 const MenuBar = { refresh () { console.log('刷新') } } const subMenu = { add () { console.log("增加"); }, del () { console.log("刪除"); } } // 現在需要 將每個對象中的方法 進行拆分成單獨類 // 并且 這些拆分后的指令需要 實現統一的方法 才能統一調用 class BaseCommand { constructor(receiver) { if (new.target === BaseCommand) { throw new Error('這個類不能被實例化') } this._receiver = receiver } // 需要每個指令重寫 這個方法 execute () { } } // MenuBar 對應的方法只有一個因此拆分的指令類一個 class RefershMenuBarCommand extends BaseCommand { constructor(receiver) { super(receiver) } execute () { this.receiver.refresh() } } // subMenu 有兩個方法這里拆成了兩個指令類 class AddSubMenuCommand extends BaseCommand { constructor(receiver) { super(receiver) } execute () { this.receiver.add() } } class DeleteSubMenuCommand extends BaseCommand { constructor(receiver) { super(receiver) } execute () { this.receiver.del() } } // Invoker調用者 將 指令command 和 received 進行匹配 function setCommand (button, command) { button.onclick = function () { // 統一收口所有指令的調度方法是 被收口是這個方法調用 command.execute() } } // 聲明指令 ,將指令 和原始對象進行組合 const refershMenuBarCommand = new RefershMenuBarCommand(MenuBar) setCommand(button1, refershMenuBarCommand) ~~~ * 結果分析 ~~~ 1.之前如果沒有采用命令模式 出現的問題就是最開始提出的假設讓兩個人來寫,一個人 負責按鈕的繪制工作,一個人負責寫這個按鈕點擊后的具體行為封裝到對象中,兩個 人的耦合性較高,負責按鈕繪制的人必須等寫按鈕邏輯的人寫完后才能調用按鈕 具體調用的對象,現在站在命令模式的角度來開,繪制按鈕的同學不在用關心你 按鈕邏輯的具體寫法,具體配合那個對象,因為所有的方法都被拆分為了指令,最后 的調用都被收口在'execute' 調用,只需要開發按鈕邏輯的同學將指令傳遞到繪制 同學寫的'setCommand ' 即'Invoker' 統一的調用者即可 ~~~ >[danger] ##### 總結 ~~~ 1.書中舉了一個訂餐的例子,我們現在來看這個例子,結合代碼分析這個理解,一個人去點餐,服務員 是一個調用者,點餐的不用知道那個廚師給我做的飯,只需要告訴調用者,調用者將這個指令告訴 對應的廚師即可 2.每一個廚師可以看作是一個對象會做的菜看做一個方法,菜單上的菜看作將每個對象 方法拆分出來的指令,點餐的不關心是誰做的,自然服務員 會將這個指令和對應廚師 這個對象做到匹配調用 ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看