命令模式(5)

命令模式定義:將請求,命令,動作等封裝成對象,這樣可以讓項目使用這些對象來參數化其他對象。是的命令的請求者和執行者解耦。


以下是一個遙控器的例子,如果按照傳統OO思想,我們一般會直接讓遙控器去調用硬件提供的API,但是這種寫法,會導致遙控器與特定的硬件API強耦合。當我們的需要接入新的設備,修改按鈕所綁定硬件命令,這時候就會相當不便。我們有個準則是,原來已經測試好的代碼,儘量不去改動。而使用命令模式就可以達到這個效果。將命令抽象成接口,所有硬件命令實現該接口,當需要調用某個硬件api,就直接調用接口的api,這樣就可以實現控制器與硬件的解耦。


代碼示例如下:

1
2
3
4
5
6
7
8
9
//命令接口
public interface Command {
 
    //執行命令
    public void execute();
     
    //回退命令
    public void undo();
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LightOffCommand implements Command {
    private String name;
    public LightOffCommand(String name) {
        super();
        this.name = name;
    }
 
    @Override
    public void execute() {
        System.out.println("關閉--"+name+"--的燈");
    }
 
    @Override
    public void undo() {
        System.out.println("打開--"+name+"--的燈");
    }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class LightOnCommand implements Command {
    private String name;
    public LightOnCommand(String name) {
        super();
        this.name = name;
    }
 
    @Override
    public void execute() {
        System.out.println("打開--"+name+"--的燈");
    }
 
    @Override
    public void undo() {
        System.out.println("關閉--"+name+"--的燈");
    }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
//空命令類的作用是,防止初始化的按鈕,沒有綁定導致空指針異常
public class NoCommand implements Command {
 
    @Override
    public void execute() {
        System.out.println("沒有綁定任何電器,所以無反應");
    }
 
    @Override
    public void undo() {
        // TODO Auto-generated method stub
    }
}


控制器類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
//遙控器App對象
public class TeleController {
    private NoCommand noCommand = new NoCommand();
    //初始遙控器只有三對命令
    private List<Command> leftButtonList;
    private List<Command> rightButtonList;
    //遙控器操作記錄
    private Stack<Command> records = new Stack<Command>();
     
    public TeleController(){
        leftButtonList = new ArrayList<Command>(3);
        rightButtonList = new ArrayList<Command>(3);
        leftButtonList.add(noCommand);
        leftButtonList.add(noCommand);
        leftButtonList.add(noCommand);
        rightButtonList.add(noCommand);
        rightButtonList.add(noCommand);
        rightButtonList.add(noCommand);
    }
     
    public void clickButton(int index, boolean left){
        if(left){
            leftButtonList.get(index).execute();
            records.push(leftButtonList.get(index));
        }else{
            rightButtonList.get(index).execute();
            records.push(rightButtonList.get(index));
        }
    }
     
    public void backButton(){
        if(!records.isEmpty()){
            records.pop().undo();
        }else {
            System.out.println("已無更多操作記錄,回退失敗");
        }
    }
     
    public void setCommand(int index, boolean left, Command command){
        if(left){
            leftButtonList.set(index, command);
        }
        else{
            rightButtonList.set(index, command);
        }
    }
     
    public void addButton(boolean left){
        if(left){
            leftButtonList.add(noCommand);
        }else {
            rightButtonList.add(noCommand);
        }
    }
     
}


1
2
3
4
5
6
7
8
9
10
11
12
13
//掃地機器人---邏輯相同,可跳過該代碼
public class RoombaOnCommand implements Command {
     
    @Override
    public void execute() {
        System.out.println("掃地機器人--開始--打掃");
    }
 
    @Override
    public void undo() {
        System.out.println("掃地機器人--停止--打掃");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
public class RoombaOffCommand implements Command {
     
    @Override
    public void execute() {
        System.out.println("掃地機器人--停止--打掃");
    }
 
    @Override
    public void undo() {
        System.out.println("掃地機器人--開始--打掃");
    }
}


主測試函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Main {
    private static final boolean leftButton = true;
    private static final boolean rightButton = false;
 
    public static void main(String[] args) {
        TeleController teleController = new TeleController();
         
        teleController.clickButton(0, leftButton);
         
        System.out.println("左邊第一欄按鈕綁定臥室燈【開啓】命令");
        teleController.setCommand(0, leftButton, new LightOnCommand("臥室燈"));
         
        System.out.println("右邊第一欄按鈕綁定臥室燈【關閉】命令");
        teleController.setCommand(0, rightButton, new LightOffCommand("臥室燈"));
         
        System.out.println("左邊第二欄按鈕綁定打掃機器人【開啓】命令");
        teleController.setCommand(1, leftButton, new RoombaOnCommand());
         
        System.out.println("右邊第二欄按鈕綁定打掃機器人【關閉】命令");
        teleController.setCommand(1, rightButton, new RoombaOffCommand());
         
         
        System.out.println("按下左邊第一個按鈕");
        teleController.clickButton(0, leftButton);
        System.out.println("按下左邊第二個按鈕");
        teleController.clickButton(1, leftButton);
        System.out.println("按下回退按鈕");
        teleController.backButton();
        System.out.println("再按下回退按鈕");
        teleController.backButton();
        System.out.println("再按下回退按鈕");
        teleController.backButton();
         
    }
 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章