Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DesignPatterns/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This project explores various design patterns and their implementations in moder

### Behavioral Design Patterns 💪

- [Command](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/command) 📝
- [Strategy](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy) 🎯
- [Execute Around Method (EAM)](src/main/java/pl/mperor/lab/java/design/pattern/behavioral/eam) ⭕

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

class Account {

private double balance;
private boolean active;

void deposit(double amount) {
balance += amount;
}

void withdraw(double amount) {
balance -= amount;
}

void changeActive() {
active = !active;
}

double getBalance() {
return balance;
}

boolean isActive() {
return active;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

record AccountDepositCommand(Account account, double deposit) implements Command {

@Override
public void execute() {
account.deposit(deposit);
}

@Override
public Command reversed() {
return new AccountWithdrawCommand(account, deposit);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

record AccountWithdrawCommand(Account account, double withdraw) implements Command {

@Override
public void execute() {
account.withdraw(withdraw);
}

@Override
public Command reversed() {
return new AccountDepositCommand(account, withdraw);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

@FunctionalInterface
public interface Command {

void execute();

default Command reversed() {
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

import java.util.Deque;
import java.util.LinkedList;

class CommandRegister {

private final Deque<Command> historyCommands = new LinkedList<>();
private final Deque<Command> redoCommands = new LinkedList<>();

void execute(Command command) {
command.execute();
historyCommands.push(command);
redoCommands.clear();
}

void undo() {
if (!historyCommands.isEmpty()) {
var command = historyCommands.pop();
redoCommands.push(command);
command.reversed().execute();
}
}

void redo() {
if (!redoCommands.isEmpty()) {
var command = redoCommands.pop();
historyCommands.push(command);
command.execute();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package pl.mperor.lab.java.design.pattern.behavioral.command;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class CommandRegistryTest {

@Test
public void testUndoRedoImplementationWithCommandPattern() {
Account account = new Account();
CommandRegister commander = new CommandRegister();
commander.execute(account::changeActive);
commander.execute(new AccountDepositCommand(account, 10));
Assert.that(account).active(true).balance(10);

commander.undo();
Assert.that(account).active(true).balance(0);

commander.undo();
Assert.that(account).active(false).balance(0);

commander.redo();
Assert.that(account).active(true).balance(0);

commander.redo();
Assert.that(account).active(true).balance(10);
}

static class Assert {

private Account account;

Assert(Account account) {
this.account = account;
}

Assert active(boolean active) {
Assertions.assertEquals(active, account.isActive());
return this;
}

Assert balance(double balance) {
Assertions.assertEquals(balance, account.getBalance());
return this;
}

static Assert that(Account account) {
return new Assert(account);
}
}
}
Loading