<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 請求發送者與接收者解耦——命令模式(一) 裝修新房的最后幾道工序之一是安裝插座和開關,通過開關可以控制一些電器的打開和關閉,例如電燈或者排氣扇。在購買開關時,我們并不知道它將來到底用于控制什么電器,也就是說,開關與電燈、排氣扇并無直接關系,一個開關在安裝之后可能用來控制電燈,也可能用來控制排氣扇或者其他電器設備。開關與電器之間通過電線建立連接,如果開關打開,則電線通電,電器工作;反之,開關關閉,電線斷電,電器停止工作。相同的開關可以通過不同的電線來控制不同的電器,如圖1所示: ![](http://img.my.csdn.net/uploads/201304/15/1366033382_9782.jpg) 圖1 開關與電燈、排氣扇示意圖 在圖1中,我們可以將開關理解成一個請求的發送者,用戶通過它來發送一個“開燈”請求,而電燈是“開燈”請求的最終接收者和處理者,在圖中,開關和電燈之間并不存在直接耦合關系,它們通過電線連接在一起,使用不同的電線可以連接不同的請求接收者,只需更換一根電線,相同的發送者(開關)即可對應不同的接收者(電器)。 在軟件開發中也存在很多與開關和電器類似的請求發送者和接收者對象,例如一個按鈕,它可能是一個“關閉窗口”請求的發送者,而按鈕點擊事件處理類則是該請求的接收者。為了降低系統的耦合度,將請求的發送者和接收者解耦,我們可以使用一種被稱之為命令模式的設計模式來設計系統,在命令模式中,發送者與接收者之間引入了新的命令對象(類似圖1中的電線),將發送者的請求封裝在命令對象中,再通過命令對象來調用接收者的方法。本章我們將學習用于將請求發送者和接收者解耦的命令模式。 1 自定義功能鍵 Sunny軟件公司開發人員為公司內部OA系統開發了一個桌面版應用程序,該應用程序為用戶提供了一系列自定義功能鍵,用戶可以通過這些功能鍵來實現一些快捷操作。Sunny軟件公司開發人員通過分析,發現不同的用戶可能會有不同的使用習慣,在設置功能鍵的時候每個人都有自己的喜好,例如有的人喜歡將第一個功能鍵設置為“打開幫助文檔”,有的人則喜歡將該功能鍵設置為“最小化至托盤”,為了讓用戶能夠靈活地進行功能鍵的設置,開發人員提供了一個“功能鍵設置”窗口,該窗口界面如圖2所示: ![](http://img.my.csdn.net/uploads/201304/15/1366033417_2468.jpg) 圖2 “功能鍵設置”界面效果圖 通過如圖2所示界面,用戶可以將功能鍵和相應功能綁定在一起,還可以根據需要來修改功能鍵的設置,而且系統在未來可能還會增加一些新的功能或功能鍵。 Sunny軟件公司某開發人員欲使用如下代碼來實現功能鍵與功能處理類之間的調用關系: ``` //FunctionButton:功能鍵類,請求發送者 class FunctionButton { private HelpHandler help; //HelpHandler:幫助文檔處理類,請求接收者 //在FunctionButton的onClick()方法中調用HelpHandler的display()方法 public void onClick() { help = new HelpHandler(); help.display(); //顯示幫助文檔 } } ``` 在上述代碼中,功能鍵類FunctionButton充當請求的發送者,幫助文檔處理類HelpHandler充當請求的接收者,在發送者FunctionButton的onClick()方法中將調用接收者HelpHandler的display()方法。顯然,如果使用上述代碼,將給系統帶來如下幾個問題: (1) 由于請求發送者和請求接收者之間存在方法的直接調用,耦合度很高,更換請求接收者必須修改發送者的源代碼,如果需要將請求接收者HelpHandler改為WindowHanlder(窗口處理類),則需要修改FunctionButton的源代碼,違背了“開閉原則”。 (2) FunctionButton類在設計和實現時功能已被固定,如果增加一個新的請求接收者,如果不修改原有的FunctionButton類,則必須增加一個新的與FunctionButton功能類似的類,這將導致系統中類的個數急劇增加。由于請求接收者HelpHandler、WindowHanlder等類之間可能不存在任何關系,它們沒有共同的抽象層,因此也很難依據“依賴倒轉原則”來設計FunctionButton。 (3) 用戶無法按照自己的需要來設置某個功能鍵的功能,一個功能鍵類的功能一旦固定,在不修改源代碼的情況下無法更換其功能,系統缺乏靈活性。 不難得知,所有這些問題的產生都是因為請求發送者FunctionButton類和請求接收者HelpHandler、WindowHanlder等類之間存在直接耦合關系,如何降低請求發送者和接收者之間的耦合度,讓相同的發送者可以對應不同的接收者?這是Sunny軟件公司開發人員在設計“功能鍵設置”模塊時不得不考慮的問題。命令模式正為解決這類問題而誕生,此時,如果我們使用命令模式,可以在一定程度上解決上述問題(注:命令模式無法解決類的個數增加的問題),下面就讓我們正式進入命令模式的學習,看看命令模式到底如何實現請求發送者和接收者解耦。 2 命令模式概述 在軟件開發中,我們經常需要向某些對象發送請求(調用其中的某個或某些方法),但是并不知道請求的接收者是誰,也不知道被請求的操作是哪個,此時,我們特別希望能夠以一種松耦合的方式來設計軟件,使得請求發送者與請求接收者能夠消除彼此之間的耦合,讓對象之間的調用關系更加靈活,可以靈活地指定請求接收者以及被請求的操作。命令模式為此類問題提供了一個較為完美的解決方案。 命令模式可以將請求發送者和接收者完全解耦,發送者與接收者之間沒有直接引用關系,發送請求的對象只需要知道如何發送請求,而不必知道如何完成請求。 命令模式定義如下: 命令模式(Command Pattern):將一個請求封裝為一個對象,從而讓我們可用不同的請求對客戶進行參數化;對請求排隊或者記錄請求日志,以及支持可撤銷的操作。命令模式是一種對象行為型模式,其別名為動作(Action)模式或事務(Transaction)模式。 命令模式的定義比較復雜,提到了很多術語,例如“用不同的請求對客戶進行參數化”、“對請求排隊”,“記錄請求日志”、“支持可撤銷操作”等,在后面我們將對這些術語進行一一講解。 命令模式的核心在于引入了命令類,通過命令類來降低發送者和接收者的耦合度,請求發送者只需指定一個命令對象,再通過命令對象來調用請求接收者的處理方法,其結構如圖3所示: ![](http://img.my.csdn.net/uploads/201304/15/1366033467_9048.jpg) 圖3 命令模式結構圖 在命令模式結構圖中包含如下幾個角色: ● Command(抽象命令類):抽象命令類一般是一個抽象類或接口,在其中聲明了用于執行請求的execute()等方法,通過這些方法可以調用請求接收者的相關操作。 ● ConcreteCommand(具體命令類):具體命令類是抽象命令類的子類,實現了在抽象命令類中聲明的方法,它對應具體的接收者對象,將接收者對象的動作綁定其中。在實現execute()方法時,將調用接收者對象的相關操作(Action)。 ● Invoker(調用者):調用者即請求發送者,它通過命令對象來執行請求。一個調用者并不需要在設計時確定其接收者,因此它只與抽象命令類之間存在關聯關系。在程序運行時可以將一個具體命令對象注入其中,再調用具體命令對象的execute()方法,從而實現間接調用請求接收者的相關操作。 ● Receiver(接收者):接收者執行與請求相關的操作,它具體實現對請求的業務處理。 命令模式的本質是對請求進行封裝,一個請求對應于一個命令,將發出命令的責任和執行命令的責任分割開。每一個命令都是一個操作:請求的一方發出請求要求執行一個操作;接收的一方收到請求,并執行相應的操作。命令模式允許請求的一方和接收的一方獨立開來,使得請求的一方不必知道接收請求的一方的接口,更不必知道請求如何被接收、操作是否被執行、何時被執行,以及是怎么被執行的。 命令模式的關鍵在于引入了抽象命令類,請求發送者針對抽象命令類編程,只有實現了抽象命令類的具體命令才與請求接收者相關聯。在最簡單的抽象命令類中只包含了一個抽象的execute()方法,每個具體命令類將一個Receiver類型的對象作為一個實例變量進行存儲,從而具體指定一個請求的接收者,不同的具體命令類提供了execute()方法的不同實現,并調用不同接收者的請求處理方法。 典型的抽象命令類代碼如下所示: ``` abstract class Command { public abstract void execute(); } ``` 對于請求發送者即調用者而言,將針對抽象命令類進行編程,可以通過構造注入或者設值注入的方式在運行時傳入具體命令類對象,并在業務方法中調用命令對象的execute()方法,其典型代碼如下所示: ``` class Invoker { private Command command; //構造注入 public Invoker(Command command) { this.command = command; } //設值注入 public void setCommand(Command command) { this.command = command; } //業務方法,用于調用命令類的execute()方法 public void call() { command.execute(); } } ``` 具體命令類繼承了抽象命令類,它與請求接收者相關聯,實現了在抽象命令類中聲明的execute()方法,并在實現時調用接收者的請求響應方法action(),其典型代碼如下所示: ``` class ConcreteCommand extends Command { private Receiver receiver; //維持一個對請求接收者對象的引用 public void execute() { receiver.action(); //調用請求接收者的業務處理方法action() } } ``` 請求接收者Receiver類具體實現對請求的業務處理,它提供了action()方法,用于執行與請求相關的操作,其典型代碼如下所示: ``` class Receiver { public void action() { //具體操作 } } ``` 思考 > 一個請求發送者能否對應多個請求接收者?如何實現?
                  <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>

                              哎呀哎呀视频在线观看