Skip to content

Implement the Behavioral Design Patterns #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 2, 2024
39 changes: 39 additions & 0 deletions src/practice/behavioral/chain/ChainDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package practice.behavioral.chain;


import java.util.Arrays;
import java.util.List;

/**
* Example of Chain of Responsibility Design Pattern
*/
public final class ChainDemo {

public static void main(final String... arguments) {

getWorkList().forEach(makeWorkerChain()::perform);
}

private static Worker makeWorkerChain() {

final var general = new General();
general.setNext(new King());

final var jailer = new Jailer();
jailer.setNext(general);

final var officer = new Officer();
officer.setNext(jailer);

return officer;
}

private static List<Work> getWorkList() {
return Arrays.asList(
new Work(WorkType.INTERROGATE, "interrogation"),
new Work(WorkType.COLLECT_TAX, "tax-collection"),
new Work(WorkType.SLAY_DRAGON, "dragon-slaying"),
new Work(WorkType.PLAN_BATTLE, "castle-defense")
);
}
}
24 changes: 24 additions & 0 deletions src/practice/behavioral/chain/General.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package practice.behavioral.chain;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@ToString
@RequiredArgsConstructor
public final class General extends Worker {

private static final int MAX_PRIORITY = 3;

@NonNull
private final int capability; // Handling Limit

public General() {
this(MAX_PRIORITY);
}

@Override
protected boolean canHandle(final @NonNull WorkType workType) {
return workType.getLevel() <= capability; // Check Work TIER
}
}
24 changes: 24 additions & 0 deletions src/practice/behavioral/chain/Jailer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package practice.behavioral.chain;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@ToString
@RequiredArgsConstructor
public final class Jailer extends Worker {

private static final int MAX_PRIORITY = 2;

@NonNull
private final int capability; // Handling Limit

public Jailer() {
this(MAX_PRIORITY);
}

@Override
protected boolean canHandle(final @NonNull WorkType workType) {
return workType.getLevel() <= capability; // Check Work TIER
}
}
22 changes: 22 additions & 0 deletions src/practice/behavioral/chain/King.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package practice.behavioral.chain;

import lombok.NonNull;
import lombok.ToString;
import lombok.extern.java.Log;

@Log
@ToString
public final class King extends Worker {

@Override
protected boolean canHandle(final @NonNull WorkType workType) {
return true; // LAST Worker should be ABLE to handle ANY Tier
}

@Override
public void perform(@NonNull final Work work) {
var name = getClass().getSimpleName(); // Fetch Worker NAME
var order = work.getDescription(); // Get ORDER Description
log.info("Worker for <" + order + "> Job => " + name);
}
}
24 changes: 24 additions & 0 deletions src/practice/behavioral/chain/Officer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package practice.behavioral.chain;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@ToString
@RequiredArgsConstructor
public final class Officer extends Worker {

private static final int MAX_PRIORITY = 1;

@NonNull
private final int capability; // Handling Limit

public Officer() {
this(MAX_PRIORITY);
}

@Override
protected boolean canHandle(final @NonNull WorkType workType) {
return workType.getLevel() <= capability; // Check Work TIER
}
}
13 changes: 13 additions & 0 deletions src/practice/behavioral/chain/Work.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package practice.behavioral.chain;

import lombok.Data;
import lombok.NonNull;

@Data
public final class Work {

@NonNull
private final WorkType workType;
@NonNull
private final String description;
}
20 changes: 20 additions & 0 deletions src/practice/behavioral/chain/WorkType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package practice.behavioral.chain;

import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@Getter
@ToString
@RequiredArgsConstructor
public enum WorkType {

COLLECT_TAX(1),
INTERROGATE(2),
PLAN_BATTLE(3),
SLAY_DRAGON(4);

@NonNull
private final int level;
}
24 changes: 24 additions & 0 deletions src/practice/behavioral/chain/Worker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package practice.behavioral.chain;

import lombok.NonNull;
import lombok.Setter;
import lombok.extern.java.Log;

@Log
@Setter
public abstract sealed class Worker permits General, Jailer, King, Officer {

protected Worker next; // Worker who is NEXT in CHAIN of Responsibility

protected abstract boolean canHandle(final @NonNull WorkType workType);

public void perform(@NonNull final Work work) {
if (canHandle(work.getWorkType())) {
var name = getClass().getSimpleName(); // Fetch Worker NAME
var order = work.getDescription(); // Get ORDER Description
log.info("Worker for <" + order + "> Job => " + name);
} else {
next.perform(work); // DELEGATE to Worker next up in CHAIN
}
}
}
28 changes: 28 additions & 0 deletions src/practice/behavioral/command/CommandDemo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package practice.behavioral.command;

/**
* Example of Command Design Pattern
*/
public final class CommandDemo {

public static void main(final String... arguments) {

final var gardenTask = new SwitchTask(new SwitchButton("Garden"));
final var toiletTask = new SwitchTask(new SwitchButton("Toilet"));
final var kitchenTask = new SwitchTask(new SwitchButton("Kitchen"));
final var bedroomTask = new SwitchTask(new SwitchButton("Bedroom"));

final var remoteControl = new RemoteControl(); // Invoker of Switch Tasks

remoteControl.pressButton(gardenTask); // Turns ON Switch at the Garden
remoteControl.pressButton(toiletTask); // Turns ON Switch at the Toilet
remoteControl.pressButton(kitchenTask); // Turns ON Switch at the Kitchen
remoteControl.pressButton(bedroomTask); // Turns ON Switch at the Bedroom

remoteControl.undoAction(); // UNDO Task = Turns OFF Switch at the Bedroom
remoteControl.undoAction(); // UNDO Task = Turns OFF Switch at the Kitchen

remoteControl.redoAction(); // REDO Task = Turns ON Switch at the Kitchen
remoteControl.redoAction(); // REDO Task = Turns ON Switch at the Bedroom
}
}
47 changes: 47 additions & 0 deletions src/practice/behavioral/command/RemoteControl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package practice.behavioral.command;

import java.util.Deque;
import java.util.LinkedList;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
import lombok.extern.java.Log;

@Log
@ToString
@EqualsAndHashCode
public final class RemoteControl {

@NonNull
private final Deque<SwitchTask> undoStack = new LinkedList<>();
@NonNull
private final Deque<SwitchTask> redoStack = new LinkedList<>();

public void pressButton(@NonNull final SwitchTask task) {
log.info("Performing Task => [" + task + "]");
task.execute(); // Toggle from CURRENT State
undoStack.offerLast(task);
}

public void undoAction() {
if (undoStack.isEmpty()) {
log.warning("No Action is available to UNDO!");
return;
}
var lastAction = undoStack.pollLast();
redoStack.offerLast(lastAction);
log.info("UNDO of Action => [" + lastAction + "]");
lastAction.execute(); // Toggle to LAST State
}

public void redoAction() {
if (redoStack.isEmpty()) {
log.warning("No Action is available to REDO!");
return;
}
var lastAction = redoStack.pollLast();
undoStack.offerLast(lastAction);
log.info("REDO of Action => [" + lastAction + "]");
lastAction.execute(); // Toggle to LAST State
}
}
27 changes: 27 additions & 0 deletions src/practice/behavioral/command/SwitchButton.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package practice.behavioral.command;

import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.java.Log;

@Log
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
public final class SwitchButton {

@NonNull
private final String location;
private boolean state = false;

public void toggleState() {
state = !state;
}

public void printState() {
var isOn = state ? "ON" : "OFF"; // Determine current state of Switch
log.info("State of <" + location + "> Switch => [" + isOn + "]");
}
}
20 changes: 20 additions & 0 deletions src/practice/behavioral/command/SwitchTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package practice.behavioral.command;

import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
public final class SwitchTask {

@NonNull
private final SwitchButton switcher;

public void execute() {
switcher.toggleState();
switcher.printState();
}
}
28 changes: 28 additions & 0 deletions src/practice/behavioral/iterator/Attic.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package practice.behavioral.iterator;

import java.util.ArrayList;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.java.Log;

@Log
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
public final class Attic {

@NonNull
private final List<Item> items;

public void takeItems(@NonNull final ItemType itemType) {
final var robber = new Robber(itemType, new ArrayList<>(items));
log.info("Searching for Item Type => [" + itemType + "]");
// log.info("ALL Items => " + getItems()); // Print ALL Items
while (robber.hasNextItem()) {
log.info("Item in Attic => [" + robber.nextItem() + "]");
}
}
}
13 changes: 13 additions & 0 deletions src/practice/behavioral/iterator/Item.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package practice.behavioral.iterator;

import lombok.Data;
import lombok.NonNull;

@Data
public final class Item {

@NonNull
private final ItemType itemType;
@NonNull
private final String description;
}
18 changes: 18 additions & 0 deletions src/practice/behavioral/iterator/ItemType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package practice.behavioral.iterator;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.ToString;

@ToString
@RequiredArgsConstructor
public enum ItemType {

ANTIC(1),
SWORD(2),
ARMOR(3),
CROWN(4);

@NonNull
private final int tier;
}
8 changes: 8 additions & 0 deletions src/practice/behavioral/iterator/Iterator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package practice.behavioral.iterator;

public sealed interface Iterator<T> permits Robber {

boolean hasNextItem(); // Check availability

T nextItem(); // Get NEXT Item by some logic
}
Loading