北風設計模式課程---29、命令模式


北風設計模式課程---29、命令模式

一、總結

一句話總結:

整體系統如何初始做好設計,會非常節約時間,而無需管事大型項目還是小型項目,無需管事面向過程還是面向對象
命令模式就是封裝了類的調用:一個類的命令列表里面存各種類,然后遍歷調用這些類的方法

 

1、如果中小型項目的結構通過MVC本身就比較清晰了,還有必要過度使用設計模式么?

沒必要:設計模式雖然讓代碼更加工整了,但是也增加了很多類和很多代碼,不一定划得來
面向過程轉面向對象也很容易。重構一下代碼就好。然后可以按照需求增加這些設計模式。
整體系統如何初始做好設計,會非常節約時間,而無需管事大型項目還是小型項目,無需管事面向過程還是面向對象

 

2、面向對象編程和面向過程編程?

照我看來,黑貓白貓,能抓到老鼠的就是好貓。面向過程配上mvc在中小型項目中也是夠用的。
面向過程轉面向對象也很容易。重構一下代碼就好。然后可以按照需求增加這些設計模式。
整體系統如何初始做好設計,會非常節約時間,而無需管事大型項目還是小型項目,無需管事面向過程還是面向對象
初始建議面向對象編程,結構清晰,不易出錯,反而會節約時間的

 

3、什么是命令模式?

Command模式通過被稱為Command的類封裝了對目標對象的調用行為以及調用參數。


   Command模式也叫命令模式 ,是行為設計模
式的一種。Command模式通過被稱為
Command的類封裝了對目標對象的調用行為以
及調用參數。

 

4、在面向對象的程序設計中,一個對象調用另一個對象,一般情況下的調用過程是怎樣的?

1、創建目標對象實例;設置調用參數;調用目標對象的方法。
2、命令模式:但在有些情況下有必要使用一個專門的類對這種調用過程加以封裝,我們把這種專門的類稱作command類。

 

5、命令模式的應用場景?

- 整個調用過程比較繁雜,或者存在多處這種調用。這時,使用Command類對該調用加以封裝,便於功能的再利用。
- 調用前后需要對調用參數進行某些處理。
- 調用前后需要進行某些額外處理,比如日志,緩存,記錄歷史操作等。

 

6、命令模式 實例?

有賣蘋果命令類,有賣香蕉命令類。小商販Peddler類封裝了賣蘋果和賣香蕉命令。有服務員Waiter類,里面有命令列表數據結構,有添加命令和刪除命令方法,也有sail方法就是一次調用蘋果或香蕉命令類的sail方法。

 

7、命令模式的角色和職責?

1、Command:Command抽象類。Command.java
2、ConcreteCommand:Command的具體實現類。AppleCommand.java;BananaCommand.java
3、Receiver:需要被調用的目標對象。Peddler.java
4、Invorker:通過Invorker執行Command對象。Waiter.java

 

 

 

 

二、內容在總結中

1、相關知識

有賣蘋果命令類,有賣香蕉命令類。小商販Peddler類封裝了賣蘋果和賣香蕉命令。有服務員Waiter類,里面有命令列表數據結構,有添加命令和刪除命令方法,也有sail方法就是一次調用蘋果或香蕉命令類的sail方法。
 
Command:Command抽象類。Command.java
ConcreteCommand:Command的具體實現類。AppleCommand.java;BananaCommand.java
Receiver:需要被調用的目標對象。Peddler.java
Invorker:通過Invorker執行Command對象。Waiter.java

 

2、代碼

Command:Command抽象類。Command.java

 

package com.ibeifemg.ex4;

public abstract class Command {
    private Peddler peddler;
    
    
    public Command(Peddler peddler) {
        this.peddler = peddler;
    }
    
    public Peddler getPeddler() {
        return peddler;
    }

    public void setPeddler(Peddler peddler) {
        this.peddler = peddler;
    }

    public abstract void sail();
}

 

 

ConcreteCommand:Command的具體實現類。

AppleCommand.java;

package com.ibeifemg.ex4;

public class AppleCommand extends Command {

    public AppleCommand(Peddler peddler) {
        super(peddler);
    }

    public void sail() {
        this.getPeddler().sailApple();
    }
    
}

 

 

BananaCommand.java

package com.ibeifemg.ex4;

public class BananaCommand extends Command{

    public BananaCommand(Peddler peddler) {
        super(peddler);
    }

    public void sail() {
        this.getPeddler().sailBanana();
    }

}

 

 

Receiver:需要被調用的目標對象。Peddler.java

package com.ibeifemg.ex4;

/*
 * 小商販
 */
public class Peddler {
    
    //賣蘋果
    public void sailApple() {
        System.out.println("賣蘋果");
    }
    
    //賣香蕉
    public void sailBanana() {
        System.out.println("賣香蕉");
    }
    
}

 

 

Invorker:通過Invorker執行Command對象。Waiter.java

package com.ibeifemg.ex4;

import java.util.ArrayList;
import java.util.List;

public class Waiter {
    private List<Command> commands = new ArrayList<Command>();


    public void setOrder(Command command) {
        commands.add(command);
    }

    public void removeOrder(Command command) {
        commands.remove(command);
    }
    
    public void sail() {
        for(Command command : commands) {
            command.sail();
        }
    }
}

 

 

客戶端調用:

 

package com.ibeifemg.ex4;

public class MainClass {
    public static void main(String[] args) {
        Peddler peddler = new Peddler();
//        peddler.sailApple();
//        peddler.sailBanana();
        
        Command appleCommand = new AppleCommand(peddler);
        Command bananaCommand = new BananaCommand(peddler);
//        appleCommand.sail();
//        bananaCommand.sail();
        Waiter waiter = new Waiter();
        
        //下訂單
        waiter.setOrder(appleCommand);
        waiter.setOrder(bananaCommand);
        
        //移除訂單某項
        waiter.removeOrder(appleCommand);
        
        waiter.sail();
    }
}

 

 

 

三、java設計模式-----23、命令模式

轉自或參考:java設計模式-----23、命令模式
https://www.cnblogs.com/xiaobai1226/p/8651632.html

  概念:

  Command模式也叫命令模式 ,是行為設計模式的一種。Command模式通過被稱為Command的類封裝了對目標對象的調用行為以及調用參數。

  命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行為型模式。請求以命令的形式包裹在對象中,並傳給調用對象。調用對象尋找可以處理該命令的合適的對象,並把該命令傳給相應的對象,該對象執行命令。

  主要解決:

  在軟件系統中,“行為請求者”與“行為實現者”通常呈現一種“緊耦合”。但在某些場合,比如要對行為進行“記錄、撤銷/重做、事務”等處理,這種無法抵御變化的緊耦合是不合適的。在這種情況下,如何將“行為請求者”與“行為實現者”解耦?將一組行為抽象為對象,實現二

者之間的松耦合。這就是命令模式(Command Pattern)。

  下面,舉一個小例子,但不是使用命令模式實現的

  新建一個Peddler類,是一個賣水果的小商販

 1 /*
 2  * 小商販
 3  */
 4 public class Peddler {
 5     /*
 6      * 賣蘋果
 7      */
 8     public void sailApple(){
 9         System.out.println("賣蘋果");
10     }
11     
12     /*
13      * 賣香蕉
14      */
15     public void sailBanana(){
16         System.out.println("賣香蕉");
17     }
18 }

  再建一個客戶端

1 public class MainClass {
2     public static void main(String[] args) {
3         Peddler peddler = new Peddler();
4         peddler.sailApple();
5         peddler.sailBanana();
6     }
7 }

  結果:

  命令模式的應用場景

  在面向對象的程序設計中,一個對象調用另一個對象,一般情況下的調用過程是:創建目標對象實例;設置調用參數;調用目標對象的方法(像剛才的例子MainClass中,創建Peddler實例,再調度其中的方法)。

  但在有些情況下有必要使用一個專門的類對這種調用過程加以封裝,我們把這種專門的類稱作command類。

  1、整個調用過程比較繁雜,或者存在多處這種調用。這時,使用Command類對該調用加以封裝,便於功能的再利用。

  2、調用前后需要對調用參數進行某些處理。

  3、調用前后需要進行某些額外處理,比如日志,緩存,記錄歷史操作等。

  命令模式的結構

  

  命令模式的角色和職責

  1、Command:Command抽象類,定義命令的接口,聲明執行的方法。。

  2、ConcreteCommand:Command的具體實現類,命令接口實現對象,是“虛”的實現;通常會持有接收者,並調用接收者的功能來完成命令要執行的操作。

  3、Receiver:需要被調用的目標對象,接收者,真正執行命令的對象。任何類都可能成為一個接收者,只要它能夠實現命令要求實現的相應功能。

  4、Invorker:通過Invorker執行Command對象,要求命令對象執行請求,通常會持有命令對象,可以持有很多的命令對象。這個是客戶端真正觸發命令並要求命令執行相應操作的地方,也就是說相當於使用命令對象的入口。

  5、Client:創建具體的命令對象,並且設置命令對象的接收者。注意這個不是我們常規意義上的客戶端,而是在組裝命令對象和接收者,或許,把這個Client稱為裝配者會更好理解,因為真正使用命令的客戶端是從Invoker來觸發執行。

 

  當然,我們的例子非常簡單,用不到命令模式,我們假設操作很復雜,用命令模式改造一下

  首先,創建類對調用過程進行一個封裝,先創建一個Command抽象父類

 1 public abstract class Command {
 2     //包含一個Receiver的引用
 3     private Peddler peddler;
 4     
 5     public Command(Peddler peddler) {
 6         super();
 7         this.peddler = peddler;
 8     }
 9 
10     public Peddler getPeddler() {
11         return peddler;
12     }
13 
14     public void setPeddler(Peddler peddler) {
15         this.peddler = peddler;
16     }
17 
18     public abstract void sail();
19 }

  接下來創建ConcreteCommand,每一個操作都要創建一個,所以我們要創建兩個Apple與Banana

 1 /*
 2  * Apple
 3  */
 4 public class AppleCommand extends Command{
 5 
 6     public AppleCommand(Peddler peddler) {
 7         super(peddler);
 8     }
 9 
10     @Override
11     public void sail() {
12         //還可以在這句話前后做額外的處理
13         this.getPeddler().sailApple();
14     }
15 
16 }
 1 /*
 2  * Banana
 3  */
 4 public class BananaCommand extends Command{
 5 
 6     public BananaCommand(Peddler peddler) {
 7         super(peddler);
 8     }
 9 
10     @Override
11     public void sail() {
12         //還可以在這句話前后做額外的處理
13         this.getPeddler().sailBanana();
14     }
15 
16 }

   最后,修改MainClass

 1 public class MainClass {
 2     public static void main(String[] args) {
 3         Peddler peddler = new Peddler();
 4         Command appleCommand = new AppleCommand(peddler);
 5         Command bananaCommand = new BananaCommand(peddler);
 6         
 7         appleCommand.sail();
 8         bananaCommand.sail();
 9         
10     }
11 }

   但是這樣還不夠好,可以看到這是直接由命令來調用sail方法的,這樣不好,我們希望由專人來賣東西,就像人家請了一個服務員一樣,所以我們再新建一個Invorker

public class Waiter {
    private Command command;

    public Command getCommand() {
        return command;
    }

    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void sail(){
        command.sail();
    }
}

 

  再修改客戶端

 1 public class MainClass {
 2     public static void main(String[] args) {
 3         Peddler peddler = new Peddler();
 4         Command appleCommand = new AppleCommand(peddler);
 5         Command bananaCommand = new BananaCommand(peddler);
 6         
 7         Waiter waiter = new Waiter();
 8         waiter.setCommand(appleCommand);
 9         waiter.sail();
10         
11         waiter.setCommand(bananaCommand);
12         waiter.sail();
13         
14     }
15 }

 

  這樣Client就直接與Invorker進行通話

  我們現在只能添加命令,卻不能移除命令,,而且一次只能有一個命令,我們繼續改造

 1 public class Waiter {
 2     private Map<String,Command> commands;
 3 
 4     public Map<String, Command> getCommands() {
 5         if(commands == null){
 6             commands = new HashMap<String,Command>();
 7         }
 8         
 9         return commands;
10     }
11 
12     public void setCommand(String key, Command command) {
13         if(commands == null){
14             commands = new HashMap<String,Command>();
15         }
16         commands.put(key, command);
17     }
18     
19     public void RemoveCommand(String key) {
20         commands.remove(key);
21     }
22 
23     public void sail(String key){
24         commands.get(key).sail();
25     }
26 }

  Client

 1 public class MainClass {
 2     public static void main(String[] args) {
 3         Peddler peddler = new Peddler();
 4         Command appleCommand = new AppleCommand(peddler);
 5         Command bananaCommand = new BananaCommand(peddler);
 6         
 7         Waiter waiter = new Waiter();
 8         waiter.setCommand("apple", appleCommand);
 9         waiter.setCommand("banana", bananaCommand);
10         
11         waiter.sail("apple");
12         waiter.sail("banana");
13         
14         waiter.RemoveCommand("apple");
15         
16     }
17 }

  這樣,就完成了,一個命令模式的例子

  命令模式的優缺點

  優點: 1、降低了系統耦合度。

      2、新的命令可以很容易添加到系統中去。

  缺點:使用命令模式可能會導致某些系統有過多的具體命令類。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM