자바/자바 자료실

[디자인 패턴] 06. 커맨드 패턴 (Command Pattern)

Chipmunks 2018. 10. 23.
728x90


커맨드 패턴 (Command Pattern)

요청 내역을 객체로 캡슐화할 수 있으며, 매개변수로 여러 가지 다른 요청 내역을 집어넣을 수 있습니다.

또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 있고, 작업취소 기능도 가능합니다.

클래스 다이어그램


콜라보레이션 다이어그램




예제 코드

- Command.java

1
2
3
4
5
6
7
package party;
 
public interface Command {
    public void execute();
    public void undo();
}
 
cs


- Light.java


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
package party;
 
public class Light {
    String location;
    int level;
 
    public Light(String location) {
        this.location = location;
    }
 
    public void on() {
        level = 100;
        System.out.println("Light is on");
    }
 
    public void off() {
        level = 0;
        System.out.println("Light is off");
    }
 
    public void dim(int level) {
        this.level = level;
        if (level == 0) {
            off();
        }
        else {
            System.out.println("Light is dimmed to " + level + "%");
        }
    }
 
    public int getLevel() {
        return level;
    }
}
 
cs


- LightOnCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class LightOnCommand implements Command {
    Light light;
 
    public LightOnCommand(Light light) {
        this.light = light;
    }
 
    public void execute() {
        light.on();
    }
 
    public void undo() {
        light.off();
    }
}
 
cs


- LightOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class LightOffCommand implements Command {
    Light light;
 
    public LightOffCommand(Light light) {
        this.light = light;
    }
 
    public void execute() {
        light.off();
    }
 
    public void undo() {
        light.on();
    }
}
 
cs


- LivingroomLightOnCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package party;
 
public class LivingroomLightOnCommand implements Command {
    Light light;
 
    public LivingroomLightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
    public void undo() {
        light.off();
    }
}
 
cs


- LivingroomLightOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package party;
 
public class LivingroomLightOffCommand implements Command {
    Light light;
 
    public LivingroomLightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
    public void undo() {
        light.on();
    }
}
 
cs


- Hottub.java


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
package party;
 
public class Hottub {
    boolean on;
    int temperature;
 
    public Hottub() {
    }
 
    public void on() {
        on = true;
    }
 
    public void off() {
        on = false;
    }
 
    public void circulate() {
        if (on) {
            System.out.println("Hottub is bubbling!");
        }
    }
 
    public void jetsOn() {
        if (on) {
            System.out.println("Hottub jets are on");
        }
    }
 
    public void jetsOff() {
        if (on) {
            System.out.println("Hottub jets are off");
        }
    }
 
    public void setTemperature(int temperature) {
        if (temperature > this.temperature) {
            System.out.println("Hottub is heating to a steaming " + temperature + " degrees");
        }
        else {
            System.out.println("Hottub is cooling to " + temperature + " degrees");
        }
        this.temperature = temperature;
    }
}
 
cs


- HottubOnCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class HottubOnCommand implements Command {
    Hottub hottub;
 
    public HottubOnCommand(Hottub hottub) {
        this.hottub = hottub;
    }
    public void execute() {
        hottub.on();
        hottub.setTemperature(104);
        hottub.circulate();
    }
    public void undo() {
        hottub.off();
    }
}
 
cs


- HottubOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class HottubOffCommand implements Command {
    Hottub hottub;
 
    public HottubOffCommand(Hottub hottub) {
        this.hottub = hottub;
    }
 
    public void execute() {
        hottub.setTemperature(98);
        hottub.off();
    }
    public void undo() {
        hottub.on();
    }
}
 
cs


- Stereo.java


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
package party;
 
public class Stereo {
    String location;
 
    public Stereo(String location) {
        this.location = location;
    }
 
    public void on() {
        System.out.println(location + " stereo is on");
    }
 
    public void off() {
        System.out.println(location + " stereo is off");
    }
 
    public void setCD() {
        System.out.println(location + " stereo is set for CD input");
    }
 
    public void setDVD() {
        System.out.println(location + " stereo is set for DVD input");
    }
 
    public void setRadio() {
        System.out.println(location + " stereo is set for Radio");
    }
 
    public void setVolume(int volume) {
        // code to set the volume
        // valid range: 1-11 (after all 11 is better than 10, right?)
        System.out.println(location + " Stereo volume set to " + volume);
    }
}
 
cs


- StereoOnCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class StereoOnCommand implements Command {
    Stereo stereo;
 
    public StereoOnCommand(Stereo stereo) {
        this.stereo = stereo;
    }
 
    public void execute() {
        stereo.on();
    }
 
    public void undo() {
        stereo.off();
    }
}
 
cs


- StereoOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class StereoOffCommand implements Command {
    Stereo stereo;
 
    public StereoOffCommand(Stereo stereo) {
        this.stereo = stereo;
    }
 
    public void execute() {
        stereo.off();
    }
 
    public void undo() {
        stereo.on();
    }
}
 
cs


- StereoOnWithCDCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package party;
 
public class StereoOnWithCDCommand implements Command {
    Stereo stereo;
 
    public StereoOnWithCDCommand(Stereo stereo) {
        this.stereo = stereo;
    }
 
    public void execute() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume(11);
    }
 
    public void undo() {
        stereo.off();
    }
}
 
cs


- TV.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package party;
 
public class TV {
    String location;
    int channel;
 
    public TV(String location) {
        this.location = location;
    }
 
    public void on() {
        System.out.println(location + " TV is on");
    }
 
    public void off() {
        System.out.println(location + " TV is off");
    }
 
    public void setInputChannel() {
        this.channel = 3;
        System.out.println(location + " TV channel is set for DVD");
    }
}
 
cs


- TVOnCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package party;
 
public class TVOnCommand implements Command {
    TV tv;
 
    public TVOnCommand(TV tv) {
        this.tv= tv;
    }
 
    public void execute() {
        tv.on();
        tv.setInputChannel();
    }
 
    public void undo() {
        tv.off();
    }
}
 
cs


- TVOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package party;
 
public class TVOffCommand implements Command {
    TV tv;
 
    public TVOffCommand(TV tv) {
        this.tv= tv;
    }
 
    public void execute() {
        tv.off();
    }
 
    public void undo() {
        tv.on();
    }
}
 
cs


- CeilingFan.java


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
package party;
 
public class CeilingFan {
    public static final int HIGH = 3;
    public static final int MEDIUM = 2;
    public static final int LOW = 1;
    public static final int OFF = 0;
    String location;
    int speed;
 
    public CeilingFan(String location) {
        this.location = location;
    }
  
    public void high() {
        // turns the ceiling fan on to high
        speed = HIGH;
        System.out.println(location + " ceiling fan is on high");
    } 
 
    public void medium() {
        // turns the ceiling fan on to medium
        speed = MEDIUM;
        System.out.println(location + " ceiling fan is on medium");
    }
 
    public void low() {
        // turns the ceiling fan on to low
        speed = LOW;
        System.out.println(location + " ceiling fan is on low");
    }
 
    public void off() {
        // turns the ceiling fan off
        speed = OFF;
        System.out.println(location + " ceiling fan is off");
    }
 
    public int getSpeed() {
        return speed;
    }
}
 
cs


- CeilingFanHighCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package party;
 
public class CeilingFanHighCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;
 
    public CeilingFanHighCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.high();
    }
    public void undo() {
        switch (prevSpeed) {
            case CeilingFan.HIGH:     ceilingFan.high(); break;
            case CeilingFan.MEDIUM: ceilingFan.medium(); break;
            case CeilingFan.LOW:     ceilingFan.low(); break;
            default:                 ceilingFan.off(); break;
        }
    }
}
 
cs


- CeilingFanMediumCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package party;
 
public class CeilingFanMediumCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;
 
    public CeilingFanMediumCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.medium();
    }
    public void undo() {
        switch (prevSpeed) {
            case CeilingFan.HIGH:     ceilingFan.high(); break;
            case CeilingFan.MEDIUM: ceilingFan.medium(); break;
            case CeilingFan.LOW:     ceilingFan.low(); break;
            default:                 ceilingFan.off(); break;
        }
    }
}
 
cs


- CeilingFanOffCommand.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package party;
 
public class CeilingFanOffCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;
 
    public CeilingFanOffCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.off();
    }
    public void undo() {
        switch (prevSpeed) {
            case CeilingFan.HIGH:     ceilingFan.high(); break;
            case CeilingFan.MEDIUM: ceilingFan.medium(); break;
            case CeilingFan.LOW:     ceilingFan.low(); break;
            default:                 ceilingFan.off(); break;
        }
    }
}
 
cs


- NoCommand.java


1
2
3
4
5
6
7
package party;
 
public class NoCommand implements Command {
    public void execute() { }
    public void undo() { }
}
 
cs


- RemoteControl.java


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
package party;
 
//
// This is the invoker
//
public class RemoteControl {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
 
    public RemoteControl() {
        onCommands = new Command[7];
        offCommands = new Command[7];
 
        Command noCommand = new NoCommand();
        for(int i=0;i<7;i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }
  
    public void setCommand(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
 
    public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
        undoCommand = onCommands[slot];
    }
 
    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }
 
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }
 
    public String toString() {
        StringBuffer stringBuff = new StringBuffer();
        stringBuff.append("\n------ Remote Control -------\n");
        for (int i = 0; i < onCommands.length; i++) {
            stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName()
                + "    " + offCommands[i].getClass().getName() + "\n");
        }
        stringBuff.append("[undo] " + undoCommand.getClass().getName() + "\n");
        return stringBuff.toString();
    }
}
 
cs


- MacroCommand.java


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
package party;
 
public class MacroCommand implements Command {
    Command[] commands;
 
    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }
 
    public void execute() {
        for (int i = 0; i < commands.length; i++) {
            commands[i].execute();
        }
    }
 
    /**
     * NOTE:  these commands have to be done backwards to ensure 
     * proper undo functionality
     */
    public void undo() {
        for (int i = commands.length -1; i >= 0; i--) {
            commands[i].undo();
        }
    }
}
 
 
cs


- RemoteLoader.java


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
package party;
 
public class RemoteLoader {
 
    public static void main(String[] args) {
 
        RemoteControl remoteControl = new RemoteControl();
 
        Light light = new Light("Living Room");
        TV tv = new TV("Living Room");
        Stereo stereo = new Stereo("Living Room");
        Hottub hottub = new Hottub();
 
        LightOnCommand lightOn = new LightOnCommand(light);
        StereoOnCommand stereoOn = new StereoOnCommand(stereo);
        TVOnCommand tvOn = new TVOnCommand(tv);
        HottubOnCommand hottubOn = new HottubOnCommand(hottub);
        LightOffCommand lightOff = new LightOffCommand(light);
        StereoOffCommand stereoOff = new StereoOffCommand(stereo);
        TVOffCommand tvOff = new TVOffCommand(tv);
        HottubOffCommand hottubOff = new HottubOffCommand(hottub);
 
        Command[] partyOn = { lightOn, stereoOn, tvOn, hottubOn};
        Command[] partyOff = { lightOff, stereoOff, tvOff, hottubOff};
  
        MacroCommand partyOnMacro = new MacroCommand(partyOn);
        MacroCommand partyOffMacro = new MacroCommand(partyOff);
 
        remoteControl.setCommand(0, partyOnMacro, partyOffMacro);
  
        System.out.println(remoteControl);
        System.out.println("--- Pushing Macro On---");
        remoteControl.onButtonWasPushed(0);
        System.out.println("--- Pushing Macro Off---");
        remoteControl.offButtonWasPushed(0);
    }
}
 
cs


댓글