Skip to content

Instantly share code, notes, and snippets.

@kishankg
Last active December 4, 2023 12:01
Show Gist options
  • Save kishankg/574791e75fdcedddc96394a389f0d7e0 to your computer and use it in GitHub Desktop.
Save kishankg/574791e75fdcedddc96394a389f0d7e0 to your computer and use it in GitHub Desktop.
Command Design Pattern
import java.util.Stack;
// Receiver: TextEditor
class TextEditor {
private StringBuilder text = new StringBuilder();
void insertText(String insertedText) {
text.append(insertedText);
}
void deleteText(int length) {
int endIndex = text.length() - length;
if (endIndex >= 0) {
text.delete(endIndex, text.length());
}
}
void displayText() {
System.out.println("Current Text: " + text.toString());
}
}
// Command Interface
interface Command {
void execute();
void undo();
}
// Concrete Command: InsertCommand
class InsertCommand implements Command {
private TextEditor textEditor;
private String insertedText;
InsertCommand(TextEditor textEditor, String insertedText) {
this.textEditor = textEditor;
this.insertedText = insertedText;
}
@Override
public void execute() {
textEditor.insertText(insertedText);
}
@Override
public void undo() {
textEditor.deleteText(insertedText.length());
}
}
// Concrete Command: DeleteCommand
class DeleteCommand implements Command {
private TextEditor textEditor;
private int deletedLength;
DeleteCommand(TextEditor textEditor, int deletedLength) {
this.textEditor = textEditor;
this.deletedLength = deletedLength;
}
@Override
public void execute() {
textEditor.deleteText(deletedLength);
}
@Override
public void undo() {
// Reinsert the deleted text for undo
textEditor.insertText("Deleted Text");
}
}
// Invoker: TextOperationInvoker
class TextOperationInvoker {
private Stack<Command> undoStack = new Stack<>();
private Stack<Command> redoStack = new Stack<>();
void executeCommand(Command command) {
command.execute();
undoStack.push(command);
redoStack.clear(); // Clear redo stack after executing a new command
}
void undo() {
if (!undoStack.isEmpty()) {
Command undoneCommand = undoStack.pop();
undoneCommand.undo();
redoStack.push(undoneCommand);
}
}
void redo() {
if (!redoStack.isEmpty()) {
Command redoneCommand = redoStack.pop();
redoneCommand.execute();
undoStack.push(redoneCommand);
}
}
}
// Client Code
public class TextEditorApp {
public static void main(String[] args) {
TextEditor textEditor = new TextEditor();
TextOperationInvoker operationInvoker = new TextOperationInvoker();
// Inserting and displaying text
operationInvoker.executeCommand(new InsertCommand(textEditor, "Hello, "));
textEditor.displayText();
// Deleting and displaying text
operationInvoker.executeCommand(new DeleteCommand(textEditor, 5));
textEditor.displayText();
// Undoing the last operation
operationInvoker.undo();
textEditor.displayText();
// Redoing the undone operation
operationInvoker.redo();
textEditor.displayText();
}
}
import java.util.Stack;
// Receiver: Account
class Account {
private String accountHolder;
private double balance;
Account(String accountHolder, double initialBalance) {
this.accountHolder = accountHolder;
this.balance = initialBalance;
}
void deposit(double amount) {
balance += amount;
System.out.println("Deposited $" + amount + ". New balance: $" + balance);
}
void withdraw(double amount) {
if (amount <= balance) {
balance -= amount;
System.out.println("Withdrawn $" + amount + ". New balance: $" + balance);
} else {
System.out.println("Insufficient funds for withdrawal.");
}
}
void displayBalance() {
System.out.println("Current balance for " + accountHolder + ": $" + balance);
}
}
// Command Interface
interface TransactionCommand {
void execute();
void undo();
}
// Concrete Command: DepositCommand
class DepositCommand implements TransactionCommand {
private Account account;
private double amount;
DepositCommand(Account account, double amount) {
this.account = account;
this.amount = amount;
}
@Override
public void execute() {
account.deposit(amount);
}
@Override
public void undo() {
account.withdraw(amount); // Undoing deposit is treated as a withdrawal
}
}
// Concrete Command: WithdrawCommand
class WithdrawCommand implements TransactionCommand {
private Account account;
private double amount;
WithdrawCommand(Account account, double amount) {
this.account = account;
this.amount = amount;
}
@Override
public void execute() {
account.withdraw(amount);
}
@Override
public void undo() {
account.deposit(amount); // Undoing withdrawal is treated as a deposit
}
}
// Concrete Command: TransferCommand
class TransferCommand implements TransactionCommand {
private Account sourceAccount;
private Account destinationAccount;
private double amount;
TransferCommand(Account sourceAccount, Account destinationAccount, double amount) {
this.sourceAccount = sourceAccount;
this.destinationAccount = destinationAccount;
this.amount = amount;
}
@Override
public void execute() {
sourceAccount.withdraw(amount);
destinationAccount.deposit(amount);
System.out.println("Transferred $" + amount + " from " + sourceAccount.getAccountHolder() +
" to " + destinationAccount.getAccountHolder());
}
@Override
public void undo() {
destinationAccount.withdraw(amount);
sourceAccount.deposit(amount);
System.out.println("Undone transfer of $" + amount + " from " + sourceAccount.getAccountHolder() +
" to " + destinationAccount.getAccountHolder());
}
}
// Invoker: TransactionManager
class TransactionManager {
private Stack<TransactionCommand> transactionStack = new Stack<>();
private Stack<TransactionCommand> redoStack = new Stack<>();
void executeTransaction(TransactionCommand transactionCommand) {
transactionCommand.execute();
transactionStack.push(transactionCommand);
redoStack.clear(); // Clear redo stack after executing a new transaction
}
void undoLastTransaction() {
if (!transactionStack.isEmpty()) {
TransactionCommand lastTransaction = transactionStack.pop();
lastTransaction.undo();
redoStack.push(lastTransaction);
}
}
void redoLastTransaction() {
if (!redoStack.isEmpty()) {
TransactionCommand redoTransaction = redoStack.pop();
redoTransaction.execute();
transactionStack.push(redoTransaction);
}
}
}
// Client Code
public class BankingApp {
public static void main(String[] args) {
Account aliceAccount = new Account("Alice", 1000.0);
Account bobAccount = new Account("Bob", 500.0);
TransactionManager transactionManager = new TransactionManager();
// Performing transactions
transactionManager.executeTransaction(new DepositCommand(aliceAccount, 200.0));
transactionManager.executeTransaction(new WithdrawCommand(bobAccount, 100.0));
transactionManager.executeTransaction(new TransferCommand(aliceAccount, bobAccount, 300.0));
// Displaying account balances
aliceAccount.displayBalance();
bobAccount.displayBalance();
// Undoing the last transaction
transactionManager.undoLastTransaction();
aliceAccount.displayBalance();
bobAccount.displayBalance();
// Redoing the undone transaction
transactionManager.redoLastTransaction();
aliceAccount.displayBalance();
bobAccount.displayBalance();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment