This is the seventh day of my participation in the August More text Challenge. For details, see:August is more challenging

Welcome to today’s learning, today we are going to learn a very powerful mode —- command mode. I’m ordering you to finish reading this article, ha, just kidding, a few more words, I will be talking about Java design patterns in detail this month, welcome to click on the avatar, follow my column, I will continue to update, come on!

Series of articles:

Singletons of design patterns

The factory model of design pattern

The builder pattern of design patterns

Proxy patterns of design patterns

The visitor pattern of design patterns

Adaptor patterns for design patterns

. Under continuous update

Without further ado, let’s get to the point

Command mode

I personally think that this pattern is used a lot in real situations, and you may not have noticed it, but by the time I’m done you’ll think, you can change things. We can think of this as an event type notification pattern, such as what I’m going to do with an event. The order is carried out with the content of the order issued.

The original definition of the command pattern was to encapsulate a request as an object, allowing us to parameterize other objects with different requests, queues, or log requests, and to support undoable operations

Note: From the definition, we can see that the command pattern is designed to encapsulate a set of operations in an object, or in general, to encapsulate a function method into an object for transport. For example, Java has supported passing functions as arguments since 8 (we’ve all experienced streams, lambda expressions, and so on). This is the core understanding of the command pattern.

See below:

From the diagram we can see the five characters (notice the arrows in the diagram) :

  • Abstract Command class (Command) : used to declare what operations need to be done. When you see commands in your code, you can tell that the Command pattern is involved

  • The concrete Command class (Command1, 2, etc.) : Implements the Command interface, which stores a receiver class and delegates the receiver to execute the concrete method when execute calls the concrete Command

  • Invoker, the client interacts with the Invoker to manipulate different command objects.

  • Abstract Receiver, declare the command operation that needs to be performed, and provide it for the client to use (see arrows in the figure)

  • Concrete receiver (Receiver1, 2, etc.) : Implements abstract receivers that receive commands and execute the real code logic. (There are as many executors as there are orders)

The key point of the command mode is to expand around the command. By abstracting different commands and encapsulating them into objects, different receivers can make corresponding operations for the same command.

Let’s dive in with a set of scenarios and code (see the class diagram above)

Code sample

A classic example of a command mode usage scenario is a Shell script. If you are familiar with Shell scripts, you will find that a Shell script is actually the Invoker here. The various ps, cat, sed and other commands in the script are called commands. The bash shell or Z shell executes the command as the receiver.

Of course, the command mode is not limited to the operating system commands, in the actual business development, may be corresponding to a set of complex code invocation logic, such as triggering data statistics, logging, link tracing, etc.

We imagine such a scene, programmers have to document on the computer, we have to use youdao cloud notes, notes, impression and memos with MAC, all three are you open, and then write while synchronous preservation, finally you close the software, which involves three commands: open, synchronization, shut down

Let’s start by creating an abstract Command class that defines a no-return method, execute.

// Command interface
public interface Command {
    void execute(a);
}
Copy the code

Open, syncSave, and Close. Each operation has an Editor (abstract receiver class). When the execute method is implemented, The Editor’s corresponding open, syncSave, and close methods are called.

// Specific command class


public class Open implements Command {
    private Editor editor;
    public Open(Editor editor) {
        this.editor = editor;
    }
    @Override
    public void execute(a) { editor.open(); }}public class SyncSave implements Command {
    private Editor editor;
    public Save(Editor editor) {
        this.editor = editor;
    }
    @Override
    public void execute(a) { editor.save(); }}public class Close implements Command{
    private Editor editor;
    public Close(Editor editor) {
        this.editor = editor;
    }
    @Override
    public void execute(a) { editor.close(); }}Copy the code

Then, we need to define the Editor’s three operation methods: open, synchronize save, and close.

public interface Editor {
    void open(a);
    void syncSave(a);
    void close(a);
}
Copy the code

Next, we implement an editor (specific receiver) that supports youdao cloud. Netease YouDaoEditor can be opened, synchronized saved and closed respectively. Here, three different operations are printed.

public class YouDaoEditor implements Editor {

    @Override
    public void open(a) {
        System.out.println("-> YouDaoEditor);
    }
    @Override
    public void syncSave(a) {
        System.out.println("-> Netease netease);
    }
    @Override
    public void close(a) {
        System.out.println("-> YouDaoEditor perform close operation"); }}Copy the code

Similarly, YinXiangEditor, an editor supporting evernote, has the same functions as YouDaoEditor.

public class YinXiangEditor implements Editor {
    @Override
    public void open(a) {
        System.out.println("-> YinXiangEditor ";);
    }
    @Override
    public void syncSave(a) {
        System.out.println("-> YinXiangEditor");
    }
    @Override
    public void close(a) {
        System.out.println("-> YinXiangEditor"); }}Copy the code

And finally, let’s call

// Define a cut
public class RunCommond {
    private final List<Command> commands;
    public RunCommond(a) {
        commands = new ArrayList<>();
    }
    public void setCommand(Command command) {
        commands.add(command);
    }
    public void run(a) { commands.forEach(Command::execute); }}/ / call
public class Client {
    public static void main(String[] args) {
        YouDaoEditor youdaoEditor = new YouDaoEditor();
        YinXiangEditor yinxiangEditor = new YinXiangEditor();
        Open youdaoOpen = new Open(youdaoEditor);
        SyncSave yinxiangSyncSave = new SyncSave(yinxiangEditor);
        RunCommond runCommond = new RunCommond();
        // For the time being, write two commands, the rest the same.runCommond.setCommand(youdaoOpen); runCommond.setCommand(yinxiangSyncSave); runCommond.run(); }}// Console output-> Netease netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease Netease, Netease NeteaseCopy the code

OK, that’s it for today.

conclusion

The use of command mode is also very limited to scenarios where commands are executed sequentially, and is not well suited for scenarios where multiple combinations are required.

The command mode encapsulates one or a group of commands into an object, which can transmit function methods as parameters and decouple the direct coupling between the client and the server. It is applicable to simple request queuing, request logging, and support for undoable operations.

Simply put, the essence of command mode is to encapsulate commands, separating the responsibility for issuing them from the responsibility for executing them.

In addition to give you a paragraph, I think it is good, can also be put into the summary of this article, of course, also applicable to all modes, I read a book is the political commissar Fu “re-learning design mode” there is such a paragraph, with you to encourage it.

Command mode is divided into command, implementer and caller. The split of these three pieces of content is also a key factor in the selection of scenarios, which can make the logic have the nature of a single responsibility, easy to expand. This implementation reduces coupling compared to the if statement and facilitates the extension of other commands and implementations. However, this design pattern also brings some problems. The combination of various commands and implementers can extend many implementation classes that need to be managed. Learning design patterns must be practiced frequently, even if it is only to imitate the implementation at the beginning. After many practices, we can find some optimized scenarios and gradually apply them to our own development, so as to improve our own design sense of the code and make the code structure more clear and easy to expand.

overtones

Thank you for reading, and if you feel you’ve learned something, please like it and follow it.

I have included this chapter in my project, click on the project below, and follow the column. I will publish dry items every day, and I will continue to enter design patterns this month.

Come on! See you next time!