DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Object Relational Behavioral Design Patterns in Java
  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Context Object Design Pattern in Java: Introduction and Key Points
  • Java: Object Pool Design Pattern

Trending

  • GDPR Compliance With .NET: Securing Data the Right Way
  • A Guide to Developing Large Language Models Part 1: Pretraining
  • Hybrid Cloud vs Multi-Cloud: Choosing the Right Strategy for AI Scalability and Security
  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  1. DZone
  2. Coding
  3. Languages
  4. Command Design Pattern In Java

Command Design Pattern In Java

By 
Brijesh Saxena user avatar
Brijesh Saxena
DZone Core CORE ·
Updated Oct. 22, 20 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
7.4K Views

Join the DZone community and get the full member experience.

Join For Free

Today, I am here to discuss another behavioral design pattern called Command Design Pattern. A very useful pattern in which we wrap the request in an object known as Command and provide it an Invoker to perform.

Command Design Pattern

  • In the Command Design Pattern, we wrap our requests in a Command object, along with all the required information to perform an action of another object.
  • The Command object knows about the Receiver and invokes methods of the receiver by supplying parameters. Values for parameters of the receiver methods are stored in the Command object.
  • The Receiver objects performs the job when the execute() method of Command gets called.
  • We pass this Command object to an Invoker object to perform the execute method. Invoker object executes the methods of the Command object and passes the required parameters to it.
  • The Invoker objects knows how to execute the command. But, it does not know anything about any concrete command. All it knows about is the command interface/abstract class.  
  • The Invoker can take different Command objects time-to-time, so the Client deals only with the Invoker to perform operations on different objects. These objects call Receiver objects.
  • The Command object collects all the details of requests and performs operations on the Receiver.
  • The Command Design Pattern supports undoable operations as well and we can have an unexecute kind of method to return the state of the object back to its original state.
  • So, the pattern makes it super easy to perform a verity of jobs/requests in a simple way by using Invoker object.
  • The Invoker may also do bookkeeping for the Command objcets. 
  • Different Command object may have different Receiver object to act on.
  • The execute method defines and performs all the operations in the sequence to complete the job.
  • The Client Application knows when and in which order to execute the commands.
  • The only drawback of this pattern is we end up creating many command classes.

So, as you can see that in the above diagram, we wrap the request in a Command object. 

Take Command1 for some request. We give all the parameter values required by the Receiver object to perform the request into Command1. Then, we set this command to Invoker and Invoker triggers the command. Command1's execute method comes into the action and performs all the operations required on Receiver object in a define order. Client gets the output via Receiver. That's it! in simple words.

Now an example to explain it.

Home Automation Application using Command Design Pattern

Suppose we like to control our home appliances with the help of a Smart Remote. The Home Appliances will act as receiver here. Smart Remote will act as an invoker. Operations on the appliances will be concrete commands and Client will be our main application. 

To make it little user-friendly, I am trying here to provide command as statement like

 'turn on bedroomlight' or 'bedroomlight switch off'

Sounds interesting? Well its not that much difficult. All I am trying here is make it super easy and without using any third party libraries; only based on Java 8 (mainly lambda's). 

I think you guess it write, we need keywords and a command interpreter which will help us to find the right command and home appliance to select and perform the operation.

So without wasting more time, here's the code.

Code for Appliance class:

Java
 




xxxxxxxxxx
1
46


 
1
package org.trishinfotech.command.devices;
2
 
          
3
public abstract class Appliance implements Comparable<Appliance> {
4
 
          
5
    protected String name;
6
    protected boolean status;
7
    
8
    public Appliance(String name) {
9
        super();
10
        if (name == null || name.trim().isEmpty()) {
11
            new IllegalArgumentException("Appliance name is mandatory for Home Automation");
12
        }
13
        this.name = name;
14
    }
15
 
          
16
    public String name() {
17
        return name;
18
    }
19
    
20
    // define operations for appliance
21
    public void on() {
22
        if (status) {
23
            System.out.printf("'%s' is already turned on!\n", name);
24
        } else {
25
            status = true;
26
            System.out.printf("Turning On '%s'\n", name);
27
        }
28
    }
29
    
30
    public void off() {
31
        if (!status) {
32
            System.out.printf("'%s' is already turned off!\n", name);
33
        } else {
34
            status = false;
35
            System.out.printf("Turning Off '%s'\n", name);
36
        }
37
    }
38
 
          
39
    // Appliance should be compared only on name.
40
    @Override
41
    public int compareTo(Appliance other) {
42
        return this.name.compareToIgnoreCase(other.name);
43
    }
44
    
45
}



I have defined common operations like 'On' and 'Off' here.

Code for Fan class:

Java
 




xxxxxxxxxx
1
34


 
1
package org.trishinfotech.command.devices;
2
 
          
3
public abstract class Fan extends Appliance {
4
 
          
5
    public static int TOP_SPEED = 4;
6
    
7
    public static int LOWEST_SPEED = 1;
8
    
9
    protected int currentSpeed = 1;
10
    
11
    public Fan(String name) {
12
        super(name);
13
    }
14
    
15
    // define operations for fan
16
    public void increase() {
17
        if (currentSpeed < TOP_SPEED) {
18
            currentSpeed++;
19
            System.out.printf("Encreasing Speed of '%s' to '%d'.\n", name, currentSpeed);
20
        } else {
21
            System.out.printf("'%s' is already running at top speed!\n", name);
22
        }
23
    }
24
    
25
    public void decrease() {
26
        if (currentSpeed > LOWEST_SPEED) {
27
            currentSpeed--;
28
            System.out.printf("Decreasing Speed of '%s' to '%d'.\n", name, currentSpeed);
29
        } else {
30
            System.out.printf("'%s' is laready running at lowest speed!\n", name);
31
        }
32
    }
33
}



I have added operations like 'Increase' and 'Decrease' here and its a sub-type of Appliance.

Code for Light class:

Java
 




xxxxxxxxxx
1
10
9


 
1
package org.trishinfotech.command.devices;
2
 
          
3
public abstract class Light extends Appliance {
4
 
          
5
    public Light(String name) {
6
        super(name);
7
    }
8
 
          
9
}



No additional operations are needed since we already have 'On' and 'Off' defined.

Code for TV class:

Java
 




xxxxxxxxxx
1
69


 
1
package org.trishinfotech.command.devices;
2
 
          
3
public abstract class TV extends Appliance {
4
 
          
5
    public static int TOP_VOLUME = 30;
6
 
          
7
    public static int LOWEST_VOLUME = 0;
8
 
          
9
    public static int TOP_CHANNEL_NO = 999;
10
 
          
11
    public static int LOWEST_CHANNEL_NO = 1;
12
 
          
13
    protected int currentVolume = 1;
14
    protected int currentChannel = 1;
15
    protected int volumeWhenMute;
16
 
          
17
    public TV(String name) {
18
        super(name);
19
    }
20
 
          
21
    // define operations for TV
22
    public void increaseVolume() {
23
        if (currentVolume < TOP_VOLUME) {
24
            currentVolume++;
25
            System.out.printf("Encreasing volume of '%s' to '%d'.\n", name, currentVolume);
26
        } else {
27
            System.out.printf("'%s' is already on top volume!\n", name);
28
        }
29
    }
30
 
          
31
    public void decreaseVolume() {
32
        if (currentVolume > LOWEST_VOLUME) {
33
            currentVolume--;
34
            System.out.printf("Decreasing volume of '%s' to '%d'.\n", name, currentVolume);
35
        } else {
36
            System.out.printf("'%s' is already on mute!\n", name);
37
        }
38
    }
39
 
          
40
    public void mute() {
41
        if (currentVolume != LOWEST_VOLUME) {
42
            volumeWhenMute = currentVolume;
43
            currentVolume = 0;
44
            System.out.printf("Putting '%s' on mute!\n", name);
45
        } else {
46
            currentVolume = volumeWhenMute;
47
            System.out.printf("Unmuting '%s'. Setting volume back to '%d'!\n", name, currentVolume);
48
        }
49
    }
50
 
          
51
    public void increaseChannel() {
52
        if (currentChannel < TOP_CHANNEL_NO) {
53
            currentChannel++;
54
            System.out.printf("Encreasing channel of '%s' to '%d'.\n", name, currentChannel);
55
        } else {
56
            System.out.printf("'%s' is already showing channel '%d'!\n", name, currentChannel);
57
        }
58
    }
59
 
          
60
    public void decreaseChannel() {
61
        if (currentChannel > LOWEST_CHANNEL_NO) {
62
            currentChannel--;
63
            System.out.printf("Decreasing channel of '%s' to '%d'.\n", name, currentChannel);
64
        } else {
65
            System.out.printf("'%s' is already showing channel '%d'!\n", name, currentChannel);
66
        }
67
    }
68
}



I have added operations like 'Increase/Decrease Volume', 'Increase/Decrease Channel'  and 'Sound Mute'.

Now lets create some classes to create actual home appliance objects. I am creating them as separate classes because bed-room-light need not to be same as kitchen light and may have some additional operations like setting color white or warm white or even multi-color. I am not adding that level of piece of code and encourage you to think on that. Also, you may enhance it for real IoT project using some controllers with raspberry pi or something similar and control your  home appliances. Please search on the Net for more information. Also if you need, I can provide additional information on that.

Code for BedRoomFan class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.bedroom;
2
 
          
3
import org.trishinfotech.command.devices.Fan;
4
 
          
5
public class BedRoomFan extends Fan {
6
 
          
7
    public BedRoomFan() {
8
        super("BedRoomFan");
9
    }
10
    
11
}



Code for BedRoomLight class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.bedroom;
2
 
          
3
import org.trishinfotech.command.devices.Light;
4
 
          
5
public class BedRoomLight extends Light {
6
 
          
7
    public BedRoomLight() {
8
        super("BedRoomLight");
9
    }
10
 
          
11
}



Code for KitchenLight class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.kitchen;
2
 
          
3
import org.trishinfotech.command.devices.Light;
4
 
          
5
public class KitchenLight extends Light {
6
 
          
7
    public KitchenLight() {
8
        super("KitchenLight");
9
    }
10
 
          
11
}



Code for Microwave class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.kitchen;
2
 
          
3
import org.trishinfotech.command.devices.Appliance;
4
 
          
5
public class Microwave extends Appliance {
6
 
          
7
    public Microwave() {
8
        super("Microwave");
9
    }
10
 
          
11
}



Code for LivingRoomFan class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.livingroom;
2
 
          
3
import org.trishinfotech.command.devices.Fan;
4
 
          
5
public class LivingRoomFan extends Fan {
6
 
          
7
    public LivingRoomFan() {
8
        super("LivingRoomFan");
9
    }
10
 
          
11
}



Code for LivingRoomLight class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.livingroom;
2
 
          
3
import org.trishinfotech.command.devices.Light;
4
 
          
5
public class LivingRoomLight extends Light {
6
 
          
7
    public LivingRoomLight() {
8
        super("LivingRoomLight");
9
    }
10
 
          
11
}
12
 
          



Code for LivingRoomTV class:

Java
 




xxxxxxxxxx
1
12


 
1
package org.trishinfotech.command.devices.livingroom;
2
 
          
3
import org.trishinfotech.command.devices.TV;
4
 
          
5
public class LivingRoomTV extends TV {
6
 
          
7
    public LivingRoomTV() {
8
        super("LivingRoomTV");
9
    }
10
 
          
11
}



Now, when all the appliances are defined along with their operations, it's time to work on Command Design Pattern. The above appliance-classes will be our Receiver objects.

Code for Command abstract class.

Java
 




xxxxxxxxxx
1
30


 
1
package org.trishinfotech.command;
2
 
          
3
import java.util.List;
4
 
          
5
import org.trishinfotech.command.devices.Appliance;
6
 
          
7
public abstract class Command {
8
 
          
9
    protected String name;
10
    protected Appliance appliance;
11
 
          
12
    public Command(String name, Appliance appliance) {
13
        super();
14
        this.name = name;
15
        this.appliance = appliance;
16
    }
17
 
          
18
    public Appliance appliance() {
19
        return appliance;
20
    }
21
 
          
22
    public String name() {
23
        return name;
24
    }
25
 
          
26
    public abstract void execute();
27
 
          
28
    public abstract List<String> keywords();
29
}
29
}



Please note that I have provided additional methods like 'keywords'. This will help us while interpreting the command.

Now, the code for concrete command classes. Just to avoid creating many class files, I wrote them as as a public static nested classes inside a public class called Commands. 

Code for Commands class:

Java
 




xxxxxxxxxx
1
152


 
1
package org.trishinfotech.command.commands;
2
 
          
3
import java.util.Arrays;
4
import java.util.List;
5
 
          
6
import org.trishinfotech.command.Command;
7
import org.trishinfotech.command.devices.Appliance;
8
import org.trishinfotech.command.devices.Fan;
9
import org.trishinfotech.command.devices.TV;
10
import org.trishinfotech.command.devices.livingroom.LivingRoomTV;
11
 
          
12
public class Commands {
13
 
          
14
    protected static String SWITCH = "switch";
15
    protected static String TURN = "turn";
16
    protected static String ON = "on";
17
    protected static String OFF = "off";
18
    protected static String START = "start";
19
    protected static String STOP = "stop";
20
    protected static String OPEN = "open";
21
    protected static String CLOSE = "close";
22
    protected static String UP = "up";
23
    protected static String DOWN = "down";
24
    protected static String STARTUP = "startup";
25
    protected static String SHUTDOWN = "shutdown";
26
    protected static String MUTE = "mute";
27
    protected static String UNMUTE = "unmute";
28
    protected static String PAUSE = "pause";
29
    protected static String INCREASE = "increase";
30
    protected static String DECREASE = "decrease";
31
    protected static String RAISE = "raise";
32
    protected static String LOWER = "lower";
33
    protected static String HIGHER = "higher";
34
    protected static String HIGH = "high";
35
    protected static String LOW = "low";
36
    protected static String SET = "set";
37
    protected static String SHOW = "show";
38
    protected static String CHANNEL = "channel";
39
    protected static String VOLUME = "volume";
40
    protected static String DISPLAY = "display";
41
 
          
42
    public static class OnCommand extends Command {
43
        public OnCommand(String name, Appliance appliance) {
44
            super(name, appliance);
45
        }
46
        @Override public void execute() {
47
            appliance.on();
48
        }
49
        @Override public List<String> keywords() {
50
            return Arrays.asList(ON, START, STARTUP);
51
        }
52
    }
53
 
          
54
    public static class OffCommand extends Command {
55
        public OffCommand(String name, Appliance appliance) {
56
            super(name, appliance);
57
        }
58
        @Override public void execute() {
59
            appliance.off();
60
        }
61
        @Override public List<String> keywords() {
62
            return Arrays.asList(OFF, STOP, SHUTDOWN);
63
        }
64
    }
65
 
          
66
    public static class IncreaseSpeedCommand extends Command {
67
        public IncreaseSpeedCommand(String name, Appliance appliance) {
68
            super(name, appliance);
69
        }
70
        @Override public void execute() {
71
            ((Fan)appliance).increase();
72
        }
73
        @Override public List<String> keywords() {
74
            return Arrays.asList(UP, INCREASE, RAISE, HIGH, HIGHER);
75
        }
76
    }
77
 
          
78
    public static class DecreaseSpeedCommand extends Command {
79
        public DecreaseSpeedCommand(String name, Appliance appliance) {
80
            super(name, appliance);
81
        }
82
        @Override public void execute() {
83
            ((Fan)appliance).decrease();
84
        }
85
        @Override public List<String> keywords() {
86
            return Arrays.asList(DOWN, DECREASE, LOW, LOWER);
87
        }
88
    }
89
 
          
90
    public static class TVIncreaseVolumeCommand extends Command {
91
        public TVIncreaseVolumeCommand(String name, Appliance appliance) {
92
            super(name, appliance);
93
        }
94
        @Override public void execute() {
95
            ((TV)appliance).increaseVolume();
96
        }
97
 
          
98
        @Override public List<String> keywords() {
99
            return Arrays.asList(UP, INCREASE, RAISE, HIGH, HIGHER, VOLUME);
100
        }
101
    }
102
 
          
103
    public static class TVIncreaseChannelCommand extends Command {
104
        public TVIncreaseChannelCommand(String name, Appliance appliance) {
105
            super(name, appliance);
106
        }
107
        @Override public void execute() {
108
            ((TV)appliance).increaseChannel();
109
        }
110
 
          
111
        @Override public List<String> keywords() {
112
            return Arrays.asList(UP, INCREASE, RAISE, HIGH, HIGHER, CHANNEL);
113
        }
114
    }
115
 
          
116
    public static class TVDecreaseVolumeCommand extends Command {
117
        public TVDecreaseVolumeCommand(String name, Appliance appliance) {
118
            super(name, appliance);
119
        }
120
        @Override public void execute() {
121
            ((TV)appliance).decreaseVolume();
122
        }
123
        @Override public List<String> keywords() {
124
            return Arrays.asList(DOWN, DECREASE, LOW, LOWER, VOLUME);
125
        }
126
    }
127
 
          
128
    public static class TVDecreaseChannelCommand extends Command {
129
        public TVDecreaseChannelCommand(String name, Appliance appliance) {
130
            super(name, appliance);
131
        }
132
        @Override public void execute() {
133
            ((TV)appliance).decreaseChannel();
134
        }
135
        @Override public List<String> keywords() {
136
            return Arrays.asList(DOWN, DECREASE, LOW, LOWER, CHANNEL);
137
        }
138
    }
139
 
          
140
    public static class TVMuteCommand extends Command {
141
        public TVMuteCommand(String name, Appliance appliance) {
142
            super(name, appliance);
143
        }
144
        @Override public void execute() {
145
            ((LivingRoomTV)appliance).mute();
146
        }
147
        @Override public List<String> keywords() {
148
            return Arrays.asList(MUTE, UNMUTE, PAUSE);
149
        }
150
    }
151
}



Please notice that I also provided keywords along with the concrete-commands to decode them correctly. I am using interpreter here to identifying the appliance and the command to perform. I will try to write another article on Interpreters to make this more clear for the audience. 

Code for CommandInterpreter class :

Java
 




xxxxxxxxxx
1
54


 
1
package org.trishinfotech.command;
2
 
          
3
import java.util.Comparator;
4
import java.util.List;
5
import java.util.Optional;
6
import java.util.stream.Collectors;
7
 
          
8
public class CommandInterpreter {
9
 
          
10
    public static Optional<Command> interpretCommand(String commandStr) {
11
        Optional<Command> command = Optional.empty();
12
        if (commandStr != null && !commandStr.trim().isEmpty()) {
13
            List<String> applianceNames = HomeAutomation.INSTANCE.applianceNames();
14
            Optional<String> applianceName = findApplianceName(commandStr, applianceNames);
15
            if (applianceName.isPresent()) {
16
                List<Command> commands = HomeAutomation.INSTANCE.applianceCommands(applianceName.get());
17
                command = findCommand(commandStr, commands);
18
            }
19
        }
20
        return command;
21
    }
22
 
          
23
    private static Optional<Command> findCommand(String commandStr, List<Command> availableCommands) {
24
        List<Command> matchingCommands = availableCommands.stream()
25
                .filter(availableCommand -> hasMatchingKeywords(availableCommand, commandStr))
26
                .collect(Collectors.toList());
27
        matchingCommands.sort(new Comparator<Command>() {
28
                    @Override
29
                    public int compare(Command cmd1, Command cmd2) {
30
                        return Integer.compare(noOfMatch(cmd2, commandStr), noOfMatch(cmd1, commandStr));
31
                    }
32
 
          
33
                    private int noOfMatch(Command cmd, String commandStr) {
34
                        return cmd.keywords().stream().filter(keyword -> hasPotentialMatch(keyword, commandStr)).collect(Collectors.toList()).size();
35
                    }
36
                });
37
        return Optional.ofNullable(matchingCommands.isEmpty() ? null : matchingCommands.get(0));
38
    }
39
 
          
40
    private static boolean hasMatchingKeywords(Command command, String commandStr) {
41
        return command.keywords().stream().filter(keyword -> hasPotentialMatch(keyword, commandStr)).findAny()
42
                .isPresent();
43
    }
44
 
          
45
    private static Optional<String> findApplianceName(String commandStr, List<String> applianceNames) {
46
        return applianceNames.stream().filter(applianceName -> hasPotentialMatch(applianceName, commandStr))
47
                .findFirst();
48
    }
49
 
          
50
    private static boolean hasPotentialMatch(String keyword, String commandStr) {
51
        return commandStr.toLowerCase().indexOf(keyword.toLowerCase()) != -1;
52
    }
53
}



This class receives the provided command string and perform keyword searching to identify the right command and appliance to perform the right action.

Code for HomeAutomation class:

Java
 




xxxxxxxxxx
1
87


 
1
package org.trishinfotech.command;
2
 
          
3
import java.util.ArrayList;
4
import java.util.Arrays;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Optional;
9
import java.util.stream.Collectors;
10
 
          
11
import org.trishinfotech.command.commands.Commands.DecreaseSpeedCommand;
12
import org.trishinfotech.command.commands.Commands.IncreaseSpeedCommand;
13
import org.trishinfotech.command.commands.Commands.OffCommand;
14
import org.trishinfotech.command.commands.Commands.OnCommand;
15
import org.trishinfotech.command.commands.Commands.TVDecreaseChannelCommand;
16
import org.trishinfotech.command.commands.Commands.TVDecreaseVolumeCommand;
17
import org.trishinfotech.command.commands.Commands.TVIncreaseChannelCommand;
18
import org.trishinfotech.command.commands.Commands.TVIncreaseVolumeCommand;
19
import org.trishinfotech.command.commands.Commands.TVMuteCommand;
20
import org.trishinfotech.command.devices.Appliance;
21
import org.trishinfotech.command.devices.bedroom.BedRoomFan;
22
import org.trishinfotech.command.devices.bedroom.BedRoomLight;
23
import org.trishinfotech.command.devices.kitchen.KitchenLight;
24
import org.trishinfotech.command.devices.kitchen.Microwave;
25
import org.trishinfotech.command.devices.livingroom.LivingRoomFan;
26
import org.trishinfotech.command.devices.livingroom.LivingRoomLight;
27
import org.trishinfotech.command.devices.livingroom.LivingRoomTV;
28
 
          
29
public class HomeAutomation {
30
 
          
31
    private Map<Appliance, List<Command>> optionsAvailable = new HashMap<Appliance, List<Command>>();
32
 
          
33
    private HomeAutomation() {
34
        Appliance bedRoomFan = new BedRoomFan();
35
        Appliance bedRoomLight = new BedRoomLight();
36
        Appliance kitchenLight = new KitchenLight();
37
        Appliance microwave = new Microwave();
38
        Appliance livingRoomFan = new LivingRoomFan();
39
        Appliance livingRoomLight = new LivingRoomLight();
40
        Appliance livingRoomTV = new LivingRoomTV();
41
        optionsAvailable.put(bedRoomFan,
42
                Arrays.asList(new OnCommand("BedRoomFan On", bedRoomFan), new OffCommand("BedRoomFan Off", bedRoomFan),
43
                        new IncreaseSpeedCommand("BedRoomFan Increase", bedRoomFan),
44
                        new DecreaseSpeedCommand("BedRoomFan Decrease", bedRoomFan)));
45
        optionsAvailable.put(bedRoomLight, Arrays.asList(new OnCommand("BedRoomLight On", bedRoomLight),
46
                new OffCommand("BedRoomLight On", bedRoomLight)));
47
        optionsAvailable.put(kitchenLight, Arrays.asList(new OnCommand("KitchenLight On", kitchenLight),
48
                new OffCommand("KitchenLight Off", kitchenLight)));
49
        optionsAvailable.put(microwave,
50
                Arrays.asList(new OnCommand("Microwave On", microwave), new OffCommand("Microwave Off", microwave)));
51
        optionsAvailable.put(livingRoomFan,
52
                Arrays.asList(new OnCommand("LivingRoomFan On", livingRoomFan),
53
                        new OffCommand("LivingRoomFan Off", livingRoomFan),
54
                        new IncreaseSpeedCommand("LivingRoomFan Increase", livingRoomFan),
55
                        new DecreaseSpeedCommand("LivingRoomFan Decrease", livingRoomFan)));
56
        optionsAvailable.put(livingRoomLight, Arrays.asList(new OnCommand("LivingRoomLight On", livingRoomLight),
57
                new OffCommand("LivingRoomLight Off", livingRoomLight)));
58
        optionsAvailable.put(livingRoomTV,
59
                Arrays.asList(new OnCommand("LivingRoomTV On", livingRoomTV),
60
                        new OffCommand("LivingRoomTV Off", livingRoomTV),
61
                        new TVIncreaseVolumeCommand("LivingRoomTV Increase Volume", livingRoomTV),
62
                        new TVIncreaseChannelCommand("LivingRoomTV Decrease Channel", livingRoomTV),
63
                        new TVDecreaseVolumeCommand("LivingRoomTV Decrease Volume", livingRoomTV),
64
                        new TVDecreaseChannelCommand("LivingRoomTV Decrease Channel", livingRoomTV),
65
                        new TVMuteCommand("LivingRoomTV Mute/Unmute", livingRoomTV)));
66
    }
67
 
          
68
    public List<String> applianceNames() {
69
        return optionsAvailable.keySet().stream().map(appliance -> appliance.name()).collect(Collectors.toList());
70
    }
71
 
          
72
    public List<Command> applianceCommands(String applianceName) {
73
        List<Command> commands = new ArrayList<Command>();
74
        if (applianceName != null && !applianceName.trim().isEmpty()) {
75
            Optional<Appliance> applianceSelected = optionsAvailable.keySet().stream()
76
                    .filter(appliance -> appliance.name().equalsIgnoreCase(applianceName.trim())).findAny();
77
            if (applianceSelected.isPresent()) {
78
                commands.addAll(optionsAvailable.get(applianceSelected.get()));
79
            }
80
        }
81
        return commands;
82
    }
83
 
          
84
    public static HomeAutomation INSTANCE = new HomeAutomation();
85
 
          
86
}



I wrote this class as a Home Automation Hub (singleton). You can read more on in my article on Singleton Design Pattern.

Code for HomeRemote class:

Java
 




xxxxxxxxxx
1
24


 
1
package org.trishinfotech.command;
2
 
          
3
public class HomeRemote {
4
 
          
5
    Command command;
6
 
          
7
    public HomeRemote() {
8
        super();
9
    }
10
    
11
    public void setCommand(Command command) {
12
        this.command = command;
13
    }
14
    
15
    public void pressButton() {
16
        System.out.println("---------------------------------------------------------------------------");
17
        System.out.printf("Executing command '%s' on appliance '%s'...\n", command.name(), command.appliance().name());
18
        command.execute();
19
        System.out.println("Done!");
20
        System.out.println("---------------------------------------------------------------------------");
21
        System.out.println("\n");
22
    }
23
}



This HomeRemote will act as Invoker for us.

Now it's time to write Main program to execute and test output.

Java
 




xxxxxxxxxx
1
33


 
1
package org.trishinfotech.command;
2
 
          
3
import java.util.Optional;
4
import java.util.Scanner;
5
 
          
6
public class Main {
7
 
          
8
    public static void main(String[] args) {
9
        String commandStr = null; 
10
        HomeRemote remote = new HomeRemote();
11
        try (Scanner scanner = new Scanner(System.in)) {
12
            do {
13
                System.out.println("Please enter command to operate on your Home Appliances (Press Ctrl + C to end)");
14
                System.out.println("-------------------------------------------------------------------------------");
15
                System.out.printf(" Available Devices: %s\n", HomeAutomation.INSTANCE.applianceNames());
16
                System.out.println("-------------------------------------------------------------------------------");
17
                System.out.print("Alexa>");
18
                commandStr = scanner.nextLine();
19
                Optional<Command> commandOption = CommandInterpreter.interpretCommand(commandStr);
20
                if (commandOption.isPresent()) {
21
                    Command command = commandOption.get();
22
                    remote.setCommand(command);
23
                    remote.pressButton();
24
                } else {
25
                    System.out.println("Sorry! I am not sure how to do that? Please try again!\n");
26
                }
27
            } while(true);
28
        }
29
    }
30
 
          
31
}



Below is the command to run this code post mvn build.

Shell
 




xxxxxxxxxx
1


 
1
java -cp command.jar org.trishinfotech.command.Main



And here's the output:

Java
 




x
109


 
1
 java -cp command.jar org.trishinfotech.command.Main
2
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
3
-------------------------------------------------------------------------------
4
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
5
-------------------------------------------------------------------------------
6
Alexa>turn on bedroomlight
7
---------------------------------------------------------------------------
8
Executing command 'BedRoomLight On' on appliance 'BedRoomLight'...
9
Turning On 'BedRoomLight'
10
Done!
11
---------------------------------------------------------------------------
12
 
          
13
 
          
14
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
15
-------------------------------------------------------------------------------
16
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
17
-------------------------------------------------------------------------------
18
Alexa>swtch on livingroomtv
19
---------------------------------------------------------------------------
20
Executing command 'LivingRoomTV On' on appliance 'LivingRoomTV'...
21
Turning On 'LivingRoomTV'
22
Done!
23
---------------------------------------------------------------------------
24
 
          
25
 
          
26
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
27
-------------------------------------------------------------------------------
28
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
29
-------------------------------------------------------------------------------
30
Alexa>decrease livingroomtv volume
31
---------------------------------------------------------------------------
32
Executing command 'LivingRoomTV Decrease Volume' on appliance 'LivingRoomTV'...
33
Decreasing volume of 'LivingRoomTV' to '0'.
34
Done!
35
---------------------------------------------------------------------------
36
 
          
37
 
          
38
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
39
-------------------------------------------------------------------------------
40
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
41
-------------------------------------------------------------------------------
42
Alexa>livingroomtv decrease volume
43
---------------------------------------------------------------------------
44
Executing command 'LivingRoomTV Decrease Volume' on appliance 'LivingRoomTV'...
45
'LivingRoomTV' is already on mute!
46
Done!
47
---------------------------------------------------------------------------
48
 
          
49
 
          
50
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
51
-------------------------------------------------------------------------------
52
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
53
-------------------------------------------------------------------------------
54
Alexa>increase volume livigroomtv
55
Sorry! I am not sure how to do that? Please try again!
56
 
          
57
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
58
-------------------------------------------------------------------------------
59
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
60
-------------------------------------------------------------------------------
61
Alexa>increase volume livingroomtv
62
---------------------------------------------------------------------------
63
Executing command 'LivingRoomTV Increase Volume' on appliance 'LivingRoomTV'...
64
Encreasing volume of 'LivingRoomTV' to '1'.
65
Done!
66
---------------------------------------------------------------------------
67
 
          
68
 
          
69
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
70
-------------------------------------------------------------------------------
71
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
72
-------------------------------------------------------------------------------
73
Alexa>increase channel livingroomtv
74
---------------------------------------------------------------------------
75
Executing command 'LivingRoomTV Decrease Channel' on appliance 'LivingRoomTV'...
76
Encreasing channel of 'LivingRoomTV' to '2'.
77
Done!
78
---------------------------------------------------------------------------
79
 
          
80
 
          
81
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
82
-------------------------------------------------------------------------------
83
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
84
-------------------------------------------------------------------------------
85
Alexa>start bedroomfan
86
---------------------------------------------------------------------------
87
Executing command 'BedRoomFan On' on appliance 'BedRoomFan'...
88
Turning On 'BedRoomFan'
89
Done!
90
---------------------------------------------------------------------------
91
 
          
92
 
          
93
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
94
-------------------------------------------------------------------------------
95
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
96
-------------------------------------------------------------------------------
97
Alexa>increase bedroomfan
98
---------------------------------------------------------------------------
99
Executing command 'BedRoomFan Increase' on appliance 'BedRoomFan'...
100
Encreasing Speed of 'BedRoomFan' to '2'.
101
Done!
102
---------------------------------------------------------------------------
103
 
          
104
 
          
105
Please enter command to operate on your Home Appliances (Press Ctrl + C to end)
106
-------------------------------------------------------------------------------
107
 Available Devices: [BedRoomLight, KitchenLight, LivingRoomFan, BedRoomFan, LivingRoomTV, LivingRoomLight, Microwave]
108
-------------------------------------------------------------------------------
109
Alexa>



Looks good!

Source Code can be found here: Command-Design-Pattern-Sample-Code

I hope this tutorial demonstrates the use of command design pattern.

Liked the article? Please don't forget to press that like button. Happy coding!

Need more articles, please visit my profile: Brijesh Saxena.

Command (computing) Java (programming language) Design Object (computer science)

Opinions expressed by DZone contributors are their own.

Related

  • Object Relational Behavioral Design Patterns in Java
  • Distribution Design Patterns in Java - Data Transfer Object (DTO) And Remote Facade Design Patterns
  • Context Object Design Pattern in Java: Introduction and Key Points
  • Java: Object Pool Design Pattern

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!