love fish大鵬一曰同風(fēng)起,扶搖直上九萬里

          常用鏈接

          統(tǒng)計(jì)

          積分與排名

          friends

          link

          最新評(píng)論

          Java中的模式 --- 命令模式的(實(shí)現(xiàn),功能,使用場(chǎng)合)及如何配合其它模式使用命令模式 (轉(zhuǎn))

          一,命令模式的實(shí)現(xiàn):
          命令模式里邊一般都有以下幾個(gè)角色:客戶端,請(qǐng)求者,命令接口,命令實(shí)現(xiàn),接受者,
          下邊是簡(jiǎn)單命令模式的實(shí)現(xiàn)代碼實(shí)現(xiàn):
          ?1public?class?Client{
          ?2????public?static?void?main(String[]?args){
          ?3????????Receiver?receiver?=?new?Receiver();
          ?4????????Command?commandOne?=?new?ConcreteCommandOne(receiver);
          ?5????????Command?commandTwo?=?new?ConcreteCommandTwo(receiver);
          ?6????????Invoker?invoker?=?new?Invoker(commandOne,commandTwo);
          ?7????????invoker.actionOne();
          ?8????????invoker.actionTwo();
          ?9????}

          10}

          11public?class?Invoker{
          12????private?Command?commandOne;
          13????private?Command?commandTwo;
          14????public?Invoker(Command?commandOne,Command?commandTwo){
          15????????this.commandOne?=?commandOne;
          16????????this.commandTwo?=?commandTwo;
          17????}

          18????public?void?actionOne(){
          19????????commandOne.execute();
          20????}

          21????public?void?actionTwo(){
          22????????commandTwo.execute();
          23????}

          24}

          25public?interface?Command{
          26????void?execute();
          27}

          28public?class?ConcreteCommandOne?implements?Command{
          29????private?Receiver?receiver
          30????public?ConcreteCommandOne(Receiver?receiver){
          31????????this.receiver?=?receiver;
          32????}

          33????public?void?execute(){
          34????????receiver.actionOne();
          35????}

          36}

          37public?class?ConcreteCommandTwo?implements?Command{
          38????private?Receiver?receiver
          39????public?ConcreteCommandTwo(Receiver?receiver){
          40????????this.receiver?=?receiver;
          41????}

          42????public?void?execute(){
          43????????receiver.actionTwo();
          44????}

          45}

          46public?class?Receiver{
          47????public?Receiver(){
          48????????//
          49????}

          50????public?void?actionOne(){
          51????????System.out.println("ActionOne?has?been?taken.");
          52????}

          53????public?void?actionTwo(){
          54????????System.out.println("ActionTwo?has?been?taken.");
          55????}

          56}

          二,命令模式的功能,好處,或者說為什么使用命令模式?
          上邊的代碼是否看起來很傻呢,本來可以這樣簡(jiǎn)單實(shí)現(xiàn)的:
          ?1public?class?Client{
          ?2????public?static?void?main(String[]?args){
          ?3????????Receiver?receiver?=?new?Receiver();
          ?4????????receiver.actionOne();
          ?5????????receiver.actionTwo();
          ?6????}

          ?7}

          ?8public?class?Receiver{
          ?9????public?Receiver(){
          10????????//
          11????}

          12????public?void?actionOne(){
          13????????System.out.println("ActionOne?has?been?taken.");
          14????}

          15????public?void?actionTwo(){
          16????????System.out.println("ActionTwo?has?been?taken.");
          17????}

          18}


          看多簡(jiǎn)潔,如果是像上邊如此簡(jiǎn)單的需求,這個(gè)才應(yīng)該是我們的選擇,但是有些情況下這樣的寫法不能解決的,
          或者說解決起來不好,所以引入命令模式.
          (1)我們須要Client和Receiver同時(shí)開發(fā),而且在開發(fā)過程中分別須要不停重購(gòu),改名
          (2)如果我們要求Redo ,Undo等功能
          (3)我們須要命令不按照調(diào)用執(zhí)行,而是按照?qǐng)?zhí)行時(shí)的情況排序,執(zhí)行
          (4)開發(fā)后期,我們發(fā)現(xiàn)必須要log哪些方法執(zhí)行了,如何在盡量少更改代碼的情況下實(shí)現(xiàn).并且漸少重復(fù)代碼
          (5)在上邊的情況下,我們的接受者有很多,不止一個(gè)
          解決辦法:
          情況一,我們可以定義一個(gè)接口,讓Receiver實(shí)現(xiàn)這個(gè)接口,Client按照接口調(diào)用。
          情況二,我們可以讓Receiver記住一些狀態(tài),例如執(zhí)行前的自己的狀態(tài),用來undo,但自己記錄自己的狀態(tài)
          ?實(shí)現(xiàn)起來比較混亂,一般都是一個(gè)累記錄另一個(gè)類的狀態(tài).
          情況三,很難實(shí)現(xiàn)
          情況四,,我們須要在每個(gè)Action,前后加上log
          情況五,相對(duì)好實(shí)現(xiàn),但是再加上這個(gè),是否感覺最終的實(shí)現(xiàn)很混亂呢
          好,我們?cè)賮砜纯疵钅J?在命令模式中,我們?cè)黾右恍┻^渡的類,這些類就是上邊的命名接口和命令實(shí)現(xiàn),
          這樣就很好的解決了情況一,情況二。我們?cè)偌尤胍粋€(gè)Invoker,這樣情況三和情況四就比較好解決了。

          如下加入Log和排序后的Invoker

          ?1public?class?Invoker{
          ?2????private?List?cmdList?=?new?ArrayList();
          ?3????public?Invoker(){
          ?4????}

          ?5????public?add(Command?command){
          ?6????????cmdList.add(command);
          ?7????}

          ?8????public?remove(Command?command){
          ?9????????cmdList.remove(command);
          10????}

          11????public?void?action(){
          12????????Command?cmd;
          13????????while((cmd?=getCmd())?!=?null){
          14????????????log("begin"+cmd.getName());
          15????????????cmd.execute();
          16????????????log("end"+cmd.getName());????????
          17????????}

          18????}

          19????public?Command?getCmd(){
          20????????//按照自定義優(yōu)先級(jí),排序取出cmd
          21????}

          22}

          23public?class?Client{
          24????public?static?void?main(String[]?args){
          25????????Receiver?receiver?=?new?Receiver();
          26????????Command?commandOne?=?new?ConcreteCommandOne(receiver);
          27????????Command?commandTwo?=?new?ConcreteCommandTwo(receiver);
          28????????Invoker?invoker?=?new?Invoker();
          29????????invoker.add(commandOne);
          30????????invoker.add(commandTwo);
          31????????iinvoker.action();
          32????}

          33}


          三,命令模式與其它模式的配合使用:
          1,看上邊的Invoker的實(shí)現(xiàn)是否很像代理模式呢,Invoker的這種實(shí)現(xiàn)其實(shí)就是一種代理模式。

          2,需求:有個(gè)固定命令組合會(huì)多次被執(zhí)行
          ?? 解決:加入合成模式,實(shí)現(xiàn)方法如下,定義一個(gè)宏命令類:

          ?1public?class?MacroCommand?implements?Command{
          ?2????private?List?cmdList?=?new?ArrayList();
          ?3????public?add(Command?command){
          ?4????????cmdList.add(command);
          ?5????}

          ?6????public?remove(Command?command){
          ?7????????cmdList.remove(command);
          ?8????}

          ?9????public?void?execute(){
          10????????Command?cmd;
          11????????for(int?i=0;i<cmdList.size();i++){
          12????????????cmd?=?(Command)cmdList.get(i);
          13????????????cmd.execute();
          14????????}

          15????}
          ????
          16}

          3,需求:須要redo undo
          ? 解決:加入備忘錄模式,一個(gè)簡(jiǎn)單的實(shí)現(xiàn)如下
          ?1public?class?ConcreteCommandOne?implements?Command{
          ?2????private?Receiver?receiver
          ?3????private?Receiver?lastReceiver;
          ?4????public?ConcreteCommandOne(Receiver?receiver){
          ?5????????this.receiver?=?receiver;
          ?6????}

          ?7????public?void?execute(){
          ?8????????record();
          ?9????????receiver.actionOne();
          10????}

          11????public?void?undo(){
          12????????//恢復(fù)狀態(tài)
          13????}

          14????public?void?redo(){
          15????????lastReceiver.actionOne();
          16????????//
          17????}

          18????public?record(){
          19????????//記錄狀態(tài)
          20????}

          21}

          4,需求:命令很多類似的地方
          ?? 解決:使用原型模式,利用clone
          ?? 這個(gè)就不寫例子了。
          四,命令模式的使用場(chǎng)合
          1,須要callback的時(shí)候,例如java awt/swing/swt中的Listening的消息方式
          2,須要對(duì)請(qǐng)求排隊(duì)執(zhí)行,命令的發(fā)送者和接受者有不同對(duì)的生命周期,就是命令執(zhí)行的時(shí)候,可能發(fā)出命令的
          Client已經(jīng)不存在了
          3,須要Redo Undo等函數(shù)
          4,須要log每條命令
          5,須要支持transaction,封裝一組數(shù)據(jù)命令的時(shí)候.
          五,最后再次總結(jié)一下命令模式的優(yōu)點(diǎn)和缺點(diǎn):
          優(yōu)點(diǎn):
          降低Client和命令接受者的耦合,是命令請(qǐng)求和命令執(zhí)行的對(duì)象分割
          便于修改和擴(kuò)張
          便于聚合多個(gè)命令
          缺點(diǎn):
          造成出現(xiàn)過多的具體命令類,太多文件。

          五,一個(gè)比較有意思的例子,來說明命令模式
          Client??????? :看電視的人
          Invoker???? :遙控器
          Command :電信號(hào)
          具體命令 :遙控器上的按鍵對(duì)應(yīng)的不同的電信號(hào)
          Receiver??? :電視機(jī)
          最后說一句,并不是全部按照模式寫一定就好,應(yīng)該根據(jù)你的需求來應(yīng)用,或者全部應(yīng)用,或者部分應(yīng)用,或者根本不用。

          posted on 2007-02-26 09:38 liaojiyong 閱讀(369) 評(píng)論(0)  編輯  收藏 所屬分類: Java

          主站蜘蛛池模板: 商城县| 迁安市| 天津市| 柳江县| 石楼县| 洛阳市| 叙永县| 金坛市| 芜湖市| 松潘县| 吉隆县| 通海县| 巴彦淖尔市| 郸城县| 简阳市| 德州市| 贵阳市| 锦州市| 梁河县| 新安县| 手机| 嘉禾县| 建阳市| 开远市| 泗洪县| 哈巴河县| 闻喜县| 青河县| 孟津县| 天祝| 胶州市| 鹤峰县| 施秉县| 阿巴嘎旗| 鹿邑县| 琼海市| 应城市| 新蔡县| 祁门县| 漳浦县| 呼伦贝尔市|