Design Pattern Recap

 Creational Design Patterns

Abstract Factory(抽象工厂)

Allows the creation of objects without specifying their concrete type

public class Main {
    public static void main(String[] args) {
        ShapeFactory factory = new Shape3DFactory(); // or new Shape2DFactory()

        Circle circle = factory.createCircle();
        Square square = factory.createSquare();

        circle.draw();
        square.draw();
    }
}

// ==== Abstract Products ====
interface Circle {
    void draw();
}

interface Square {
    void draw();
}

// ==== 2D Concrete Products ====
class Circle2D implements Circle {
    public void draw() {
        System.out.println("Drawing 2D Circle");
    }
}

class Square2D implements Square {
    public void draw() {
        System.out.println("Drawing 2D Square");
    }
}

// ==== 3D Concrete Products ====
class Circle3D implements Circle {
    public void draw() {
        System.out.println("Rendering 3D Circle");
    }
}

class Square3D implements Square {
    public void draw() {
        System.out.println("Rendering 3D Square");
    }
}

// ==== Abstract Factory ====
interface ShapeFactory {
    Circle createCircle();
    Square createSquare();
}

// ==== Concrete Factories ====
class Shape2DFactory implements ShapeFactory {
    public Circle createCircle() {
        return new Circle2D();
    }
    public Square createSquare() {
        return new Square2D();
    }
}

class Shape3DFactory implements ShapeFactory {
    public Circle createCircle() {
        return new Circle3D();
    }
    public Square createSquare() {
        return new Square3D();
    }
}

Builder(建造者)

Uses to create complex objects

public class Main {
    public static void main(String[] args) {
        User user = new User.Builder("Alice", "alice@example.com")
                .setPhone("123-456-7890")
                .setAddress("123 Main St")
                .build();

        System.out.println(user);
    }
}

// ==== User class with Builder ====
class User {
    // Required parameters
    private final String name;
    private final String email;

    // Optional parameters
    private final String phone;
    private final String address;

    private User(Builder builder) {
        this.name = builder.name;
        this.email = builder.email;
        this.phone = builder.phone;
        this.address = builder.address;
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', email='" + email + "', phone='" + phone + "', address='" + address + "'}";
    }

    // ==== Builder ====
    public static class Builder {
        private final String name;
        private final String email;

        private String phone;
        private String address;

        public Builder(String name, String email) {
            this.name = name;
            this.email = email;
        }

        public Builder setPhone(String phone) {
            this.phone = phone;
            return this;
        }

        public Builder setAddress(String address) {
            this.address = address;
            return this;
        }

        public User build() {
            return new User(this);
        }
    }
}

Factory Method(工厂方法)

Creates objects without specifying the exact class to create.

public class Main {
    public static void main(String[] args) {
        ShapeFactory circleFactory = new CircleFactory();
        Shape circle = circleFactory.createShape();
        circle.draw();

        ShapeFactory squareFactory = new SquareFactory();
        Shape square = squareFactory.createShape();
        square.draw();
    }
}

// ==== Product Interface ====
interface Shape {
    void draw();
}

// ==== Concrete Products ====
class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

class Square implements Shape {
    public void draw() {
        System.out.println("Drawing Square");
    }
}

// ==== Creator (Factory) ====
abstract class ShapeFactory {
    public abstract Shape createShape(); // Factory Method
}

// ==== Concrete Creators ====
class CircleFactory extends ShapeFactory {
    public Shape createShape() {
        return new Circle();
    }
}

class SquareFactory extends ShapeFactory {
    public Shape createShape() {
        return new Square();
    }
}

Prototype(原型)

Creates a new object from an existing object

public class Main {
    public static void main(String[] args) {
        Circle originalCircle = new Circle(5);
        Circle copiedCircle = (Circle) originalCircle.clone();

        originalCircle.draw();
        copiedCircle.draw();

        System.out.println("Original == Copy? " + (originalCircle == copiedCircle));
    }
}

// ==== Prototype Interface ====
interface Shape extends Cloneable {
    Shape clone();
    void draw();
}

// ==== Concrete Prototype: Circle ====
class Circle implements Shape {
    private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    public void draw() {
        System.out.println("Drawing Circle with radius: " + radius);
    }

    public Shape clone() {
        return new Circle(this.radius);
    }
}

// ==== Concrete Prototype: Rectangle ====
class Rectangle implements Shape {
    private int width, height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    public void draw() {
        System.out.println("Drawing Rectangle " + width + "x" + height);
    }

    public Shape clone() {
        return new Rectangle(this.width, this.height);
    }
}

Singleton(单例)

Ensure only one instance of an object is created

public class Main {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = Singleton.getInstance();

        instance1.showMessage();
        System.out.println("Same instance? " + (instance1 == instance2));
    }
}

// ==== Singleton Class ====
class Singleton {
    private static Singleton instance;

    private Singleton() {
        // private constructor to prevent instantiation
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }

    public void showMessage() {
        System.out.println("Hello from Singleton!");
    }
}


Structural Design Patterns

Adapter(适配器)

Allows for two incompatible classes to work together by wrapping an interface around one of the existing classes

public class Main {
    public static void main(String[] args) {
        AudioPlayer player = new AudioPlayer();

        player.play("mp3", "song.mp3");
        player.play("mp4", "video.mp4");
        player.play("vlc", "movie.vlc");
        player.play("avi", "clip.avi"); // unsupported
    }
}

// ==== Target Interface ====
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// ==== Adaptee Interface ====
interface AdvancedMediaPlayer {
    void playVlc(String fileName);
    void playMp4(String fileName);
}

// ==== Concrete Adaptees ====
class VlcPlayer implements AdvancedMediaPlayer {
    public void playVlc(String fileName) {
        System.out.println("Playing VLC file: " + fileName);
    }
    public void playMp4(String fileName) {
        // do nothing
    }
}

class Mp4Player implements AdvancedMediaPlayer {
    public void playVlc(String fileName) {
        // do nothing
    }
    public void playMp4(String fileName) {
        System.out.println("Playing MP4 file: " + fileName);
    }
}

// ==== Adapter ====
class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer advancedPlayer;

    public MediaAdapter(String audioType) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedPlayer = new VlcPlayer();
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedPlayer = new Mp4Player();
        }
    }

    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("vlc")) {
            advancedPlayer.playVlc(fileName);
        } else if (audioType.equalsIgnoreCase("mp4")) {
            advancedPlayer.playMp4(fileName);
        }
    }
}

// ==== Client ====
class AudioPlayer implements MediaPlayer {
    MediaAdapter adapter;

    public void play(String audioType, String fileName) {
        if (audioType.equalsIgnoreCase("mp3")) {
            System.out.println("Playing MP3 file: " + fileName);
        } else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
            adapter = new MediaAdapter(audioType);
            adapter.play(audioType, fileName);
        } else {
            System.out.println("Invalid media type: " + audioType);
        }
    }
}

Bridge(桥接)

Decouples an abstraction so two classes can vary independently.

public class Main {
    public static void main(String[] args) {
        Renderer vector = new VectorRenderer();
        Renderer raster = new RasterRenderer();

        Shape circle1 = new Circle(vector, 5);
        Shape circle2 = new Circle(raster, 10);

        circle1.draw();
        circle2.draw();
    }
}

// ==== Implementation Hierarchy ====
interface Renderer {
    void renderCircle(float radius);
}

class VectorRenderer implements Renderer {
    public void renderCircle(float radius) {
        System.out.println("Drawing circle with vector renderer, radius: " + radius);
    }
}

class RasterRenderer implements Renderer {
    public void renderCircle(float radius) {
        System.out.println("Drawing circle with raster renderer, radius: " + radius);
    }
}

// ==== Abstraction Hierarchy ====
abstract class Shape {
    protected Renderer renderer;

    public Shape(Renderer renderer) {
        this.renderer = renderer;
    }

    abstract void draw();
}

class Circle extends Shape {
    private float radius;

    public Circle(Renderer renderer, float radius) {
        super(renderer);
        this.radius = radius;
    }

    public void draw() {
        renderer.renderCircle(radius);
    }
}

Composite(组合)

Takes a group of objects into a single object

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Graphic circle1 = new Circle();
        Graphic square1 = new Square();
        
        CompositeGraphic group = new CompositeGraphic();
        group.add(circle1);
        group.add(square1);

        Graphic circle2 = new Circle();
        group.add(circle2);

        group.draw();
    }
}

// ==== Component ====
interface Graphic {
    void draw();
}

// ==== Leaf ====
class Circle implements Graphic {
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

class Square implements Graphic {
    public void draw() {
        System.out.println("Drawing Square");
    }
}

// ==== Composite ====
class CompositeGraphic implements Graphic {
    private List children = new ArrayList<>();

    public void add(Graphic g) {
        children.add(g);
    }

    public void remove(Graphic g) {
        children.remove(g);
    }

    public void draw() {
        for (Graphic g : children) {
            g.draw();
        }
    }
}

Decorator(装饰器)

Allows for an object's behavior to be extended dynamically at run time

public class Main {
    public static void main(String[] args) {
        Text simpleText = new PlainText("Hello");

        Text boldText = new BoldDecorator(simpleText);
        Text italicText = new ItalicDecorator(boldText);

        System.out.println(italicText.render());  // Output: Hello
    }
}

// ==== Component Interface ====
interface Text {
    String render();
}

// ==== Concrete Component ====
class PlainText implements Text {
    private String content;

    public PlainText(String content) {
        this.content = content;
    }

    public String render() {
        return content;
    }
}

// ==== Base Decorator ====
abstract class TextDecorator implements Text {
    protected Text inner;

    public TextDecorator(Text inner) {
        this.inner = inner;
    }
}

// ==== Concrete Decorators ====
class BoldDecorator extends TextDecorator {
    public BoldDecorator(Text inner) {
        super(inner);
    }

    public String render() {
        return "" + inner.render() + "";
    }
}

class ItalicDecorator extends TextDecorator {
    public ItalicDecorator(Text inner) {
        super(inner);
    }

    public String render() {
        return "" + inner.render() + "";
    }
}

Facade(外观)

Provides a simple interface to a more complex underlying object

public class Main {
    public static void main(String[] args) {
        // Subsystem components
        Amplifier amp = new Amplifier();
        DVDPlayer dvd = new DVDPlayer();
        Lights lights = new Lights();

        // Facade
        HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, dvd, lights);
        
        homeTheater.watchMovie("Inception");
        System.out.println("---");
        homeTheater.endMovie();
    }
}

// ==== Subsystem Classes ====
class Amplifier {
    void on() { System.out.println("Amplifier ON"); }
    void off() { System.out.println("Amplifier OFF"); }
}

class DVDPlayer {
    void on() { System.out.println("DVD Player ON"); }
    void play(String movie) { System.out.println("Playing movie: " + movie); }
    void stop() { System.out.println("Stopping DVD"); }
    void off() { System.out.println("DVD Player OFF"); }
}

class Lights {
    void dim() { System.out.println("Lights dimmed"); }
    void on() { System.out.println("Lights ON"); }
}

// ==== Facade ====
class HomeTheaterFacade {
    private Amplifier amp;
    private DVDPlayer dvd;
    private Lights lights;

    public HomeTheaterFacade(Amplifier amp, DVDPlayer dvd, Lights lights) {
        this.amp = amp;
        this.dvd = dvd;
        this.lights = lights;
    }

    public void watchMovie(String movie) {
        System.out.println("Get ready to watch a movie...");
        lights.dim();
        amp.on();
        dvd.on();
        dvd.play(movie);
    }

    public void endMovie() {
        System.out.println("Shutting movie theater down...");
        dvd.stop();
        dvd.off();
        amp.off();
        lights.on();
    }
}

Flyweight(享元)

Reduces the cost of complex object models

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        CharacterFactory factory = new CharacterFactory();

        TextEditor editor = new TextEditor(factory);
        editor.type('a', 1, 1);
        editor.type('b', 1, 2);
        editor.type('a', 1, 3);  // reused flyweight

        editor.display();
    }
}

// ==== Flyweight Interface ====
interface Character {
    void display(int x, int y); // extrinsic state passed at runtime
}

// ==== Concrete Flyweight ====
class ConcreteCharacter implements Character {
    private final char symbol; // intrinsic state

    public ConcreteCharacter(char symbol) {
        this.symbol = symbol;
    }

    public void display(int x, int y) {
        System.out.printf("Character '%c' at (%d, %d)%n", symbol, x, y);
    }
}

// ==== Flyweight Factory ====
class CharacterFactory {
    private Map pool = new HashMap<>();

    public Character get(char symbol) {
        return pool.computeIfAbsent(symbol, s -> new ConcreteCharacter(s));
    }
}

// ==== Client ====
class TextEditor {
    private final CharacterFactory factory;
    private final Map characters = new HashMap<>();
    private int idCounter = 0;

    public TextEditor(CharacterFactory factory) {
        this.factory = factory;
    }

    public void type(char symbol, int x, int y) {
        Character sharedChar = factory.get(symbol);
        characters.put(idCounter++, new PositionedChar(sharedChar, x, y));
    }

    public void display() {
        for (PositionedChar pc : characters.values()) {
            pc.character.display(pc.x, pc.y);
        }
    }

    private static class PositionedChar {
        Character character;
        int x, y;

        PositionedChar(Character character, int x, int y) {
            this.character = character;
            this.x = x;
            this.y = y;
        }
    }
}

Proxy(代理)

Provides a placeholder interface to an underlying object to control access, reduce cost, or reduce complexity

public class Main {
    public static void main(String[] args) {
        Image image = new ImageProxy("photo.jpg");

        System.out.println("Image created but not loaded.");
        System.out.println("Now displaying image...");
        image.display(); // triggers actual loading
        System.out.println("Displaying again...");
        image.display(); // doesn't load again
    }
}

// ==== Subject Interface ====
interface Image {
    void display();
}

// ==== Real Subject ====
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk(); // expensive operation
    }

    private void loadFromDisk() {
        System.out.println("Loading image from disk: " + filename);
    }

    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// ==== Proxy ====
class ImageProxy implements Image {
    private RealImage realImage;
    private String filename;

    public ImageProxy(String filename) {
        this.filename = filename;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // lazy loading
        }
        realImage.display();
    }
}


Behavior Design Patterns

Chain of Responsibility(责任链)

Delegates commands to a chain of processing objects

public class Main {
    public static void main(String[] args) {
        Logger loggerChain = createLoggerChain();

        loggerChain.log(Logger.INFO, "This is an info message.");
        loggerChain.log(Logger.DEBUG, "This is a debug message.");
        loggerChain.log(Logger.ERROR, "This is an error message.");
    }

    private static Logger createLoggerChain() {
        Logger errorLogger = new ErrorLogger();
        Logger debugLogger = new DebugLogger();
        Logger infoLogger = new InfoLogger();

        errorLogger.setNext(debugLogger);
        debugLogger.setNext(infoLogger);

        return errorLogger; // head of the chain
    }
}

// ==== Abstract Handler ====
abstract class Logger {
    public static final int INFO = 1;
    public static final int DEBUG = 2;
    public static final int ERROR = 3;

    protected int level;
    protected Logger next;

    public void setNext(Logger next) {
        this.next = next;
    }

    public void log(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (next != null) {
            next.log(level, message);
        }
    }

    protected abstract void write(String message);
}

// ==== Concrete Handlers ====
class InfoLogger extends Logger {
    public InfoLogger() {
        this.level = INFO;
    }

    protected void write(String message) {
        System.out.println("INFO: " + message);
    }
}

class DebugLogger extends Logger {
    public DebugLogger() {
        this.level = DEBUG;
    }

    protected void write(String message) {
        System.out.println("DEBUG: " + message);
    }
}

class ErrorLogger extends Logger {
    public ErrorLogger() {
        this.level = ERROR;
    }

    protected void write(String message) {
        System.out.println("ERROR: " + message);
    }
}

Command(命令)

Creates objects which encapsulate actions and parameters

public class Main {
    public static void main(String[] args) {
        Light light = new Light();

        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);

        RemoteControl remote = new RemoteControl();
        remote.setCommand(lightOn);
        remote.pressButton();

        remote.setCommand(lightOff);
        remote.pressButton();
    }
}

// ==== Command Interface ====
interface Command {
    void execute();
}

// ==== Receiver ====
class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }

    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// ==== Concrete Commands ====
class LightOnCommand implements Command {
    private Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.turnOn();
    }
}

class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.turnOff();
    }
}

// ==== Invoker ====
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

Interpreter(解释器)

Accesses the elements of an object sequentially without exposing its underlying representation

public class Main {
    public static void main(String[] args) {
        // Expression: true AND false
        Expression expr1 = new AndExpression(new TerminalExpression(true), new TerminalExpression(false));
        System.out.println("true AND false = " + expr1.interpret());

        // Expression: true OR false
        Expression expr2 = new OrExpression(new TerminalExpression(true), new TerminalExpression(false));
        System.out.println("true OR false = " + expr2.interpret());
    }
}

// ==== Expression Interface ====
interface Expression {
    boolean interpret();
}

// ==== Terminal Expression ====
class TerminalExpression implements Expression {
    private final boolean value;

    public TerminalExpression(boolean value) {
        this.value = value;
    }

    public boolean interpret() {
        return value;
    }
}

// ==== Non-terminal Expressions ====
class AndExpression implements Expression {
    private final Expression left;
    private final Expression right;

    public AndExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean interpret() {
        return left.interpret() && right.interpret();
    }
}

class OrExpression implements Expression {
    private final Expression left;
    private final Expression right;

    public OrExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean interpret() {
        return left.interpret() || right.interpret();
    }
}

Iterator(迭代器)

Accesses the elements of an object sequentially without exposing its underlying representation.

public class Main {
    public static void main(String[] args) {
        NameRepository names = new NameRepository();

        Iterator it = names.getIterator();
        while (it.hasNext()) {
            System.out.println("Name: " + it.next());
        }
    }
}

// ==== Iterator Interface ====
interface Iterator {
    boolean hasNext();
    Object next();
}

// ==== Aggregate Interface ====
interface Container {
    Iterator getIterator();
}

// ==== Concrete Aggregate ====
class NameRepository implements Container {
    private String[] names = {"Alice", "Bob", "Charlie", "Diana"};

    public Iterator getIterator() {
        return new NameIterator();
    }

    // ==== Concrete Iterator ====
    private class NameIterator implements Iterator {
        int index = 0;

        public boolean hasNext() {
            return index < names.length;
        }

        public Object next() {
            if (this.hasNext()) {
                return names[index++];
            }
            return null;
        }
    }
}

Mediator(中介者)

Allows loose coupling between classes by being the only class that has detailed knowledge of their methods

public class Main {
    public static void main(String[] args) {
        ChatRoomMediator chatRoom = new ChatRoom();

        User alice = new User("Alice", chatRoom);
        User bob = new User("Bob", chatRoom);
        User charlie = new User("Charlie", chatRoom);

        chatRoom.addUser(alice);
        chatRoom.addUser(bob);
        chatRoom.addUser(charlie);

        alice.send("Hi everyone!");
        bob.send("Hey Alice!");
    }
}

// ==== Mediator Interface ====
interface ChatRoomMediator {
    void sendMessage(String message, User sender);
    void addUser(User user);
}

// ==== Concrete Mediator ====
class ChatRoom implements ChatRoomMediator {
    private List users = new ArrayList<>();

    public void addUser(User user) {
        users.add(user);
    }

    public void sendMessage(String message, User sender) {
        for (User u : users) {
            if (u != sender) {
                u.receive(message, sender.getName());
            }
        }
    }
}

// ==== Colleague ====
class User {
    private String name;
    private ChatRoomMediator mediator;

    public User(String name, ChatRoomMediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }

    public String getName() {
        return name;
    }

    public void send(String message) {
        System.out.println(name + " sends: " + message);
        mediator.sendMessage(message, this);
    }

    public void receive(String message, String senderName) {
        System.out.println(name + " receives from " + senderName + ": " + message);
    }
}

Memento(备忘录)

Provides the ability to restore an object to its previous state

public class Main {
    public static void main(String[] args) {
        TextEditor editor = new TextEditor();

        editor.setText("Version 1");
        editor.save();  // Save state

        editor.setText("Version 2");
        editor.save();  // Save state

        editor.setText("Version 3");

        System.out.println("Current: " + editor.getText());
        editor.undo();
        System.out.println("After undo: " + editor.getText());
        editor.undo();
        System.out.println("After second undo: " + editor.getText());
    }
}

// ==== Originator ====
class TextEditor {
    private String text;
    private final History history = new History();

    public void setText(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    public void save() {
        history.addMemento(new Memento(text));
    }

    public void undo() {
        Memento m = history.getLastMemento();
        if (m != null) {
            text = m.getState();
        }
    }
}

// ==== Memento ====
class Memento {
    private final String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }
}

// ==== Caretaker ====
class History {
    private final java.util.Stack mementos = new java.util.Stack<>();

    public void addMemento(Memento m) {
        mementos.push(m);
    }

    public Memento getLastMemento() {
        if (!mementos.isEmpty()) {
            return mementos.pop();
        }
        return null;
    }
}

Observer(观察者)

Is a publish/subscribe pattern which allows a number of observer objects to see an event

public class Main {
    public static void main(String[] args) {
        NewsAgency agency = new NewsAgency();

        Subscriber alice = new Subscriber("Alice");
        Subscriber bob = new Subscriber("Bob");

        agency.addObserver(alice);
        agency.addObserver(bob);

        agency.setNews("Breaking: Observer pattern in action!");
        agency.setNews("Update: Java makes it easy!");
    }
}

// ==== Observer Interface ====
interface Observer {
    void update(String news);
}

// ==== Concrete Observer ====
class Subscriber implements Observer {
    private String name;

    public Subscriber(String name) {
        this.name = name;
    }

    public void update(String news) {
        System.out.println(name + " received news: " + news);
    }
}

// ==== Subject ====
class NewsAgency {
    private List observers = new ArrayList<>();
    private String news;

    public void addObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void setNews(String news) {
        this.news = news;
        notifyObservers();
    }

    private void notifyObservers() {
        for (Observer o : observers) {
            o.update(news);
        }
    }
}

State(状态)

Allows an object to alter its behavior when its internal state changes

public class Main {
    public static void main(String[] args) {
        DeviceContext context = new DeviceContext();

        context.pressPowerButton();  // Turning ON...
        context.pressPowerButton();  // Turning OFF...
        context.pressPowerButton();  // Turning ON...
    }
}

// ==== State Interface ====
interface State {
    void pressPowerButton(DeviceContext context);
}

// ==== Concrete States ====
class OnState implements State {
    public void pressPowerButton(DeviceContext context) {
        System.out.println("Turning OFF...");
        context.setState(new OffState());
    }
}

class OffState implements State {
    public void pressPowerButton(DeviceContext context) {
        System.out.println("Turning ON...");
        context.setState(new OnState());
    }
}

// ==== Context ====
class DeviceContext {
    private State state;

    public DeviceContext() {
        state = new OffState();  // default state
    }

    public void setState(State state) {
        this.state = state;
    }

    public void pressPowerButton() {
        state.pressPowerButton(this);
    }
}

Strategy(策略)

Allows one of a family of algorithms to be selected on-the-fly at run-time

public class Main {
    public static void main(String[] args) {
        Context context;

        context = new Context(new AddStrategy());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new SubtractStrategy());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new MultiplyStrategy());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

// ==== Strategy Interface ====
interface Strategy {
    int doOperation(int a, int b);
}

// ==== Concrete Strategies ====
class AddStrategy implements Strategy {
    public int doOperation(int a, int b) {
        return a + b;
    }
}

class SubtractStrategy implements Strategy {
    public int doOperation(int a, int b) {
        return a - b;
    }
}

class MultiplyStrategy implements Strategy {
    public int doOperation(int a, int b) {
        return a * b;
    }
}

// ==== Context ====
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int a, int b) {
        return strategy.doOperation(a, b);
    }
}

Template Method(模版)

Defines the skeleton of an algorithm as an abstract class, allowing its sub-classes to provide concrete behavior

public abstract class AbstractBatchStep {

    // Template Method
    public final void executeStep() {
        beforeStep();
        process();
        afterStep();
    }

    protected void beforeStep() {
        System.out.println("Default before step logic");
    }

    protected abstract void process();  // to be implemented by subclass

    protected void afterStep() {
        System.out.println("Default after step logic");
    }
}

public class MyCustomStep extends AbstractBatchStep {

    @Override
    protected void process() {
        System.out.println("Custom step processing logic");
    }
}

public class BatchRunner {
    public static void main(String[] args) {
        AbstractBatchStep step = new MyCustomStep();
        step.executeStep();  // Template method pattern in action
    }
}

@Bean
public ItemReader myReader() {
    return new ListItemReader<>(List.of("one", "two", "three"));
}

@Bean
public ItemProcessor myProcessor() {
    return item -> item.toUpperCase();
}

@Bean
public ItemWriter myWriter() {
    return items -> items.forEach(System.out::println);
}

@Bean
public Job myJob(JobBuilderFactory jobBuilders, StepBuilderFactory stepBuilders) {
    return jobBuilders.get("myJob")
            .start(myStep(stepBuilders))
            .build();
}

@Bean
public Step myStep(StepBuilderFactory stepBuilders) {
    return stepBuilders.get("myStep")
            .chunk(10)
            .reader(myReader())
            .processor(myProcessor())
            .writer(myWriter())
            .build();
}

Visitor(访问者)

Separates an algorithm from an object structure by moving the hierarchy of methods into one object

public class Main {
    public static void main(String[] args) {
        DocumentElement[] elements = {
            new Paragraph("Hello, world!"),
            new Image("diagram.png")
        };

        DocumentVisitor renderVisitor = new RenderVisitor();
        DocumentVisitor exportVisitor = new ExportVisitor();

        System.out.println("Rendering:");
        for (DocumentElement element : elements) {
            element.accept(renderVisitor);
        }

        System.out.println("\nExporting:");
        for (DocumentElement element : elements) {
            element.accept(exportVisitor);
        }
    }
}

// ==== Visitor Interface ====
interface DocumentVisitor {
    void visit(Paragraph paragraph);
    void visit(Image image);
}

// ==== Element Interface ====
interface DocumentElement {
    void accept(DocumentVisitor visitor);
}

// ==== Concrete Elements ====
class Paragraph implements DocumentElement {
    String text;

    public Paragraph(String text) {
        this.text = text;
    }

    public void accept(DocumentVisitor visitor) {
        visitor.visit(this);
    }
}

class Image implements DocumentElement {
    String fileName;

    public Image(String fileName) {
        this.fileName = fileName;
    }

    public void accept(DocumentVisitor visitor) {
        visitor.visit(this);
    }
}

// ==== Concrete Visitors ====
class RenderVisitor implements DocumentVisitor {
    public void visit(Paragraph paragraph) {
        System.out.println("Rendering paragraph: " + paragraph.text);
    }

    public void visit(Image image) {
        System.out.println("Rendering image: " + image.fileName);
    }
}

class ExportVisitor implements DocumentVisitor {
    public void visit(Paragraph paragraph) {
        System.out.println("Exporting paragraph to PDF: " + paragraph.text);
    }

    public void visit(Image image) {
        System.out.println("Exporting image to PDF: " + image.fileName);
    }
}


Comments