<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    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),接受者,
    下邊是簡單命令模式的實(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}

    二,命令模式的功能,好處,或者說為什么使用命令模式?
    上邊的代碼是否看起來很傻呢,本來可以這樣簡單實(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}


    看多簡潔,如果是像上邊如此簡單的需求,這個(gè)才應(yīng)該是我們的選擇,但是有些情況下這樣的寫法不能解決的,
    或者說解決起來不好,所以引入命令模式.
    (1)我們須要Client和Receiver同時(shí)開發(fā),而且在開發(fā)過程中分別須要不停重購,改名
    (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è)簡單的實(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 閱讀(364) 評(píng)論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 日韩中文字幕免费| 亚洲综合av永久无码精品一区二区| 国产精品亚洲玖玖玖在线观看| 亚洲AV无码一区二区乱子伦| 亚洲成年网站在线观看| 久久精品无码免费不卡| 青娱乐免费在线视频| 国产成人精品久久亚洲| 亚洲另类春色国产精品| 国产成人无码免费看片软件| 成人免费视频69| 色噜噜亚洲精品中文字幕| 国产亚洲精品VA片在线播放| 国产日韩一区二区三免费高清| 成人a视频片在线观看免费| 亚洲AV无码精品色午夜果冻不卡| 亚洲国产成人无码AV在线| 亚洲国产精品免费视频| 免费a级毛片在线观看| 亚洲国产精品日韩在线| 久久国产精品免费| 免费的一级黄色片| 1区1区3区4区产品亚洲| 一级做a爰片久久毛片免费看| 性做久久久久久久免费看| 亚洲国产精品无码久久久不卡| 亚洲无码一区二区三区| 日本一卡精品视频免费| 内射无码专区久久亚洲| 亚洲日韩国产精品乱-久| 午夜免费福利视频| 中文字幕亚洲专区| 国产亚洲视频在线观看网址 | 中美日韩在线网免费毛片视频| 又粗又大又黑又长的免费视频| 国产亚洲一区二区在线观看| 日韩亚洲人成在线综合| 毛片免费全部播放一级| 亚洲电影免费观看| 久久精品中文字幕免费| 亚洲综合网站色欲色欲|