Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!
Команда

Команда на Java

Команда — это поведенческий паттерн, позволяющий заворачивать запросы или простые операции в отдельные объекты.

Это позволяет откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.

Сложность:

Популярность:

Применимость: Паттерн можно часто встретить в Java-коде, особенно когда нужно откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.

Примеры Команд в стандартных библиотеках Java:

Признаки применения паттерна: Классы команд построены вокруг одного действия и имеют очень узкий контекст. Объекты команд часто подаются в обработчики событий элементов GUI. Практически любая реализация отмены использует принципа команд.

Команды текстового редактора и их отмена

По реакции на действия пользователя, текстовый редактор создаёт объекты команд. Каждая команда выполняет некоторое действие, а затем попадают в стек истории.

Теперь, чтобы выполнить отмену, мы берём последнюю команду из списка и выполняем обратное действие либо восстанавливаем состояние редактора, сохранённое в этой команде.

commands

commands/Command.java: Абстрактная базовая комманда

package refactoring_guru.command.example.commands; import refactoring_guru.command.example.editor.Editor; public abstract class Command { public Editor editor; private String backup; Command(Editor editor) { this.editor = editor; } void backup() { backup = editor.textField.getText(); } public void undo() { editor.textField.setText(backup); } public abstract boolean execute(); } 

commands/CopyCommand.java: Команда копирования

package refactoring_guru.command.example.commands; import refactoring_guru.command.example.editor.Editor; public class CopyCommand extends Command { public CopyCommand(Editor editor) { super(editor); } @Override public boolean execute() { editor.clipboard = editor.textField.getSelectedText(); return false; } } 

commands/PasteCommand.java: Команда вставки

package refactoring_guru.command.example.commands; import refactoring_guru.command.example.editor.Editor; public class PasteCommand extends Command { public PasteCommand(Editor editor) { super(editor); } @Override public boolean execute() { if (editor.clipboard == null || editor.clipboard.isEmpty()) return false; backup(); editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition()); return true; } } 

commands/CutCommand.java: Команда вырезания

package refactoring_guru.command.example.commands; import refactoring_guru.command.example.editor.Editor; public class CutCommand extends Command { public CutCommand(Editor editor) { super(editor); } @Override public boolean execute() { if (editor.textField.getSelectedText().isEmpty()) return false; backup(); String source = editor.textField.getText(); editor.clipboard = editor.textField.getSelectedText(); editor.textField.setText(cutString(source)); return true; } private String cutString(String source) { String start = source.substring(0, editor.textField.getSelectionStart()); String end = source.substring(editor.textField.getSelectionEnd()); return start + end; } } 

commands/CommandHistory.java: История команд

package refactoring_guru.command.example.commands; import java.util.Stack; public class CommandHistory { private Stack<Command> history = new Stack<>(); public void push(Command c) { history.push(c); } public Command pop() { return history.pop(); } public boolean isEmpty() { return history.isEmpty(); } } 

editor

editor/Editor.java: Оболочка текстового редактора

package refactoring_guru.command.example.editor; import refactoring_guru.command.example.commands.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class Editor { public JTextArea textField; public String clipboard; private CommandHistory history = new CommandHistory(); public void init() { JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)"); JPanel content = new JPanel(); frame.setContentPane(content); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); textField = new JTextArea(); textField.setLineWrap(true); content.add(textField); JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER)); JButton ctrlC = new JButton("Ctrl+C"); JButton ctrlX = new JButton("Ctrl+X"); JButton ctrlV = new JButton("Ctrl+V"); JButton ctrlZ = new JButton("Ctrl+Z"); Editor editor = this; ctrlC.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { executeCommand(new CopyCommand(editor)); } }); ctrlX.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { executeCommand(new CutCommand(editor)); } }); ctrlV.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { executeCommand(new PasteCommand(editor)); } }); ctrlZ.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { undo(); } }); buttons.add(ctrlC); buttons.add(ctrlX); buttons.add(ctrlV); buttons.add(ctrlZ); content.add(buttons); frame.setSize(450, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); } private void executeCommand(Command command) { if (command.execute()) { history.push(command); } } private void undo() { if (history.isEmpty()) return; Command command = history.pop(); if (command != null) { command.undo(); } } } 

Demo.java: Клиентский код

package refactoring_guru.command.example; import refactoring_guru.command.example.editor.Editor; public class Demo { public static void main(String[] args) { Editor editor = new Editor(); editor.init(); } } 

OutputDemo.png: Результат выполнения

Команда на других языках программирования

Команда на C# Команда на C++ Команда на Go Команда на PHP Команда на Python Команда на Ruby Команда на Rust Команда на Swift Команда на TypeScript