Behavioral Patterns

Strategy, Observer, Command, and State

Behavioral Design Patterns

Behavioral patterns characterize the ways in which classes or objects interact and distribute responsibility. They help in defining the communication between objects.

Strategy Pattern

Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

java
// Strategy Pattern
// Strategy interface
interface SortStrategy {
    void sort(int[] array);
}

class BubbleSort implements SortStrategy {
    public void sort(int[] arr) {
        System.out.println("Bubble sorting...");
        // Bubble sort implementation
        for (int i = 0; i < arr.length - 1; i++)
            for (int j = 0; j < arr.length - i - 1; j++)
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp;
                }
    }
}

class QuickSort implements SortStrategy {
    public void sort(int[] arr) {
        System.out.println("Quick sorting...");
        quickSort(arr, 0, arr.length - 1);
    }
    private void quickSort(int[] arr, int low, int high) { /* ... */ }
}

class MergeSort implements SortStrategy {
    public void sort(int[] arr) {
        System.out.println("Merge sorting...");
        // merge sort implementation
    }
}

// Context
class Sorter {
    private SortStrategy strategy;

    public void setStrategy(SortStrategy strategy) {
        this.strategy = strategy;
    }

    public void sort(int[] data) {
        strategy.sort(data);
    }
}

// Usage — switch algorithms at runtime
Sorter sorter = new Sorter();
int[] data = {5, 2, 8, 1, 9};

sorter.setStrategy(new BubbleSort()); // Small arrays
sorter.sort(data);

sorter.setStrategy(new QuickSort());  // Large arrays
sorter.sort(data);

Command Pattern

java
// Command Pattern with Undo
// Command interface
interface Command {
    void execute();
    void undo();
}

// Receiver
class TextEditor {
    private StringBuilder content = new StringBuilder();

    public void insertText(String text, int pos) {
        content.insert(pos, text);
    }

    public void deleteText(int pos, int length) {
        content.delete(pos, pos + length);
    }

    public String getContent() { return content.toString(); }
}

// Concrete commands
class InsertCommand implements Command {
    private TextEditor editor;
    private String text;
    private int position;

    InsertCommand(TextEditor e, String t, int p) {
        editor = e; text = t; position = p;
    }

    public void execute() { editor.insertText(text, position); }
    public void undo() { editor.deleteText(position, text.length()); }
}

// Invoker with history
class CommandManager {
    private Stack<Command> history = new Stack<>();

    public void executeCommand(Command cmd) {
        cmd.execute();
        history.push(cmd);
    }

    public void undo() {
        if (!history.isEmpty()) {
            history.pop().undo();
        }
    }
}