高级04-Java 设计模式:常用模式详解与实战

发布于:2025-07-26 ⋅ 阅读:(22) ⋅ 点赞:(0)

设计模式(Design Pattern)是软件开发中解决常见问题的经典方案。它们提供了一种可重用的、经过验证的代码结构,使得程序更加灵活、可扩展,并且易于维护。Java 作为一门面向对象的编程语言,广泛支持各种设计模式的应用。理解并熟练使用这些模式,对于编写高质量的 Java 代码至关重要。

本博客将详细介绍 Java 中常用的 23 种设计模式,按照它们的分类——**创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)**进行讲解。每个模式都会结合实际案例,提供完整的代码示例和使用场景,帮助读者深入理解设计模式的应用方式。

一、创建型模式

创建型模式关注对象的创建机制,旨在解耦对象的创建与使用,提高系统的灵活性和可扩展性。常见的创建型模式包括:单例模式、工厂模式、抽象工厂模式、建造者模式和原型模式

1. 单例模式(Singleton Pattern)

单例模式确保一个类只有一个实例,并提供全局访问点。它适用于需要共享资源的场景,例如数据库连接池、日志管理器等。

代码示例:
public class Singleton {
    // 私有静态实例
    private static Singleton instance;

    // 私有构造函数
    private Singleton() {}

    // 提供全局访问方法
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

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

// 使用示例
public class Main {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();

        singleton1.showMessage();
        singleton2.showMessage();

        // 验证是否为同一个实例
        System.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));
    }
}
输出:
Hello from Singleton!
Hello from Singleton!
singleton1 == singleton2: true
说明:
  • 采用双重检查锁定(Double-Checked Locking)确保线程安全。
  • 单例模式适用于需要全局唯一实例的场景。

2. 工厂模式(Factory Pattern)

工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。它适用于需要根据条件创建不同对象的场景,例如支付系统、数据库连接等。

代码示例:
// 抽象产品接口
interface Shape {
    void draw();
}

// 具体产品类
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

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

// 工厂类
class ShapeFactory {
    public Shape getShape(String shapeType) {
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        }
        return null;
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();

        Shape shape1 = shapeFactory.getShape("CIRCLE");
        shape1.draw();

        Shape shape2 = shapeFactory.getShape("SQUARE");
        shape2.draw();
    }
}
输出:
Drawing Circle
Drawing Square
说明:
  • 工厂模式将对象的创建逻辑封装在工厂类中,客户端无需关心具体实现。
  • 适用于需要根据参数动态创建对象的场景。

3. 抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。它适用于需要创建一组相关对象的场景,例如跨平台的 UI 组件库。

代码示例:
// 抽象产品接口 A
interface Button {
    void render();
}

// 抽象产品接口 B
interface Checkbox {
    void render();
}

// 具体产品 A1
class WindowsButton implements Button {
    @Override
    public void render() {
        System.out.println("Render a button in Windows style.");
    }
}

// 具体产品 B1
class WindowsCheckbox implements Checkbox {
    @Override
    public void render() {
        System.out.println("Render a checkbox in Windows style.");
    }
}

// 具体产品 A2
class MacButton implements Button {
    @Override
    public void render() {
        System.out.println("Render a button in Mac style.");
    }
}

// 具体产品 B2
class MacCheckbox implements Checkbox {
    @Override
    public void render() {
        System.out.println("Render a checkbox in Mac style.");
    }
}

// 抽象工厂
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具体工厂 1
class WindowsFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new WindowsButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new WindowsCheckbox();
    }
}

// 具体工厂 2
class MacFactory implements GUIFactory {
    @Override
    public Button createButton() {
        return new MacButton();
    }

    @Override
    public Checkbox createCheckbox() {
        return new MacCheckbox();
    }
}

// 客户端代码
public class Application {
    private Button button;
    private Checkbox checkbox;

    public Application(GUIFactory factory) {
        button = factory.createButton();
        checkbox = factory.createCheckbox();
    }

    public void render() {
        button.render();
        checkbox.render();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        String os = "MAC"; // 假设当前操作系统为 Mac

        GUIFactory factory;
        if (os.equals("MAC")) {
            factory = new MacFactory();
        } else {
            factory = new WindowsFactory();
        }

        Application app = new Application(factory);
        app.render();
    }
}
输出:
Render a button in Mac style.
Render a checkbox in Mac style.
说明:
  • 抽象工厂模式适用于需要创建一组相关对象的场景。
  • 客户端代码无需关心具体产品类,只需调用工厂接口即可。

4. 建造者模式(Builder Pattern)

建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。它适用于对象的创建过程复杂、需要分步骤构造的场景,例如生成不同配置的计算机、不同套餐的披萨等。

代码示例:
// 产品类
class Computer {
    private String CPU;
    private String RAM;
    private String storage;

    public void setCPU(String CPU) {
        this.CPU = CPU;
    }

    public void setRAM(String RAM) {
        this.RAM = RAM;
    }

    public void setStorage(String storage) {
        this.storage = storage;
    }

    @Override
    public String toString() {
        return "Computer [CPU=" + CPU + ", RAM=" + RAM + ", Storage=" + storage + "]";
    }
}

// 建造者接口
interface ComputerBuilder {
    void buildCPU();
    void buildRAM();
    void buildStorage();
    Computer getComputer();
}

// 具体建造者
class GamingComputerBuilder implements ComputerBuilder {
    private Computer computer;

    public GamingComputerBuilder() {
        computer = new Computer();
    }

    @Override
    public void buildCPU() {
        computer.setCPU("Intel i9");
    }

    @Override
    public void buildRAM() {
        computer.setRAM("32GB");
    }

    @Override
    public void buildStorage() {
        computer.setStorage("1TB SSD");
    }

    @Override
    public Computer getComputer() {
        return computer;
    }
}

// 指挥者类
class Director {
    private ComputerBuilder builder;

    public void setBuilder(ComputerBuilder builder) {
        this.builder = builder;
    }

    public Computer constructComputer() {
        builder.buildCPU();
        builder.buildRAM();
        builder.buildStorage();
        return builder.getComputer();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Director director = new Director();
        ComputerBuilder builder = new GamingComputerBuilder();

        director.setBuilder(builder);
        Computer computer = director.constructComputer();

        System.out.println(computer);
    }
}
输出:
Computer [CPU=Intel i9, RAM=32GB, Storage=1TB SSD]
说明:
  • 建造者模式适用于需要分步骤构建复杂对象的场景。
  • 指挥者类负责控制构建流程,建造者类负责具体实现。

5. 原型模式(Prototype Pattern)

原型模式通过克隆已有对象来创建新对象,而不是通过实例化类。它适用于对象的创建成本较高、需要频繁创建相似对象的场景,例如数据库连接、配置对象等。

代码示例:
// 实现 Cloneable 接口
class Prototype implements Cloneable {
    private String data;

    public Prototype(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Prototype prototype1 = new Prototype("Initial Data");
        Prototype prototype2 = (Prototype) prototype1.clone();

        System.out.println("prototype1 data: " + prototype1.getData());
        System.out.println("prototype2 data: " + prototype2.getData());

        // 修改 prototype2 的数据,不影响 prototype1
        prototype2.setData("Modified Data");
        System.out.println("After modification:");
        System.out.println("prototype1 data: " + prototype1.getData());
        System.out.println("prototype2 data: " + prototype2.getData());
    }
}
输出:
prototype1 data: Initial Data
prototype2 data: Initial Data
After modification:
prototype1 data: Initial Data
prototype2 data: Modified Data
说明:
  • 原型模式适用于需要创建多个相似对象的场景。
  • 通过 clone() 方法创建对象,避免重复初始化,提高性能。

二、结构型模式

结构型模式关注对象和类的组合方式,用于构建更大、更复杂的系统结构。常见的结构型模式包括:适配器模式、代理模式、装饰器模式、外观模式、组合模式、桥接模式和享元模式

6. 适配器模式(Adapter Pattern)

适配器模式将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以一起工作。它适用于需要兼容旧系统、第三方库或不同接口的场景。

代码示例:
// 已有接口
interface MediaPlayer {
    void play(String audioType, String fileName);
}

// 已有具体类
class AudioPlayer implements MediaPlayer {
    @Override
    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")) {
            // 假设不支持这些格式
            System.out.println("Format not supported: " + audioType);
        }
    }
}

// 新接口
interface AdvancedMediaPlayer {
    void playVlc(String fileName);
    void playMp4(String fileName);
}

// 新实现类
class VlcPlayer implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        System.out.println("Playing VLC file: " + fileName);
    }

    @Override
    public void playMp4(String fileName) {
        // 不支持
    }
}

class Mp4Player implements AdvancedMediaPlayer {
    @Override
    public void playVlc(String fileName) {
        // 不支持
    }

    @Override
    public void playMp4(String fileName) {
        System.out.println("Playing MP4 file: " + fileName);
    }
}

// 适配器类
class MediaAdapter implements MediaPlayer {
    AdvancedMediaPlayer advancedMusicPlayer;

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

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

// 使用示例
public class Main {
    public static void main(String[] args) {
        MediaPlayer audioPlayer = new AudioPlayer();

        audioPlayer.play("mp3", "song.mp3");
        audioPlayer.play("vlc", "movie.vlc");
        audioPlayer.play("mp4", "video.mp4");
    }
}
输出:
Playing MP3 file: song.mp3
Playing VLC file: movie.vlc
Playing MP4 file: video.mp4
说明:
  • 适配器模式适用于需要兼容不同接口的场景。
  • 通过适配器类,可以将不兼容的接口转换为客户端期望的接口。

7. 代理模式(Proxy Pattern)

代理模式为对象提供一个替身或占位符,以控制对对象的访问。它适用于需要对对象的访问进行控制的场景,例如远程调用、权限控制、延迟加载等。

代码示例:
// 接口
interface Image {
    void display();
}

// 真实类
class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk(fileName);
    }

    private void loadFromDisk(String fileName) {
        System.out.println("Loading " + fileName);
    }

    @Override
    public void display() {
        System.out.println("Displaying " + fileName);
    }
}

// 代理类
class ProxyImage implements Image {
    private RealImage realImage;
    private String fileName;

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

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(fileName);
        }
        realImage.display();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");

        // 图像不会立即加载
        System.out.println("Image created, not loaded yet.");
        image.display(); // 第一次调用时加载
        System.out.println("Displaying again...");
        image.display(); // 再次调用时不会重复加载
    }
}
输出:
Image created, not loaded yet.
Loading test.jpg
Displaying test.jpg
Displaying again...
Displaying test.jpg
说明:
  • 代理模式适用于需要控制对象访问的场景。
  • 可用于实现延迟加载、权限控制、远程调用等功能。

8. 装饰器模式(Decorator Pattern)

装饰器模式动态地给对象添加职责,比继承更灵活。它适用于需要在运行时动态添加功能的场景,例如 Java 的 I/O 流、GUI 组件增强等。

代码示例:
// 抽象组件
interface Coffee {
    double cost();
    String description();
}

// 具体组件
class SimpleCoffee implements Coffee {
    @Override
    public double cost() {
        return 2.0;
    }

    @Override
    public String description() {
        return "Simple Coffee";
    }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee;

    public CoffeeDecorator(Coffee coffee) {
        this.decoratedCoffee = coffee;
    }

    @Override
    public double cost() {
        return decoratedCoffee.cost();
    }

    @Override
    public String description() {
        return decoratedCoffee.description();
    }
}

// 具体装饰器 1
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.5;
    }

    @Override
    public String description() {
        return super.description() + ", Milk";
    }
}

// 具体装饰器 2
class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public double cost() {
        return super.cost() + 0.2;
    }

    @Override
    public String description() {
        return super.description() + ", Sugar";
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Coffee coffee = new SimpleCoffee();
        System.out.println(coffee.description() + " $" + coffee.cost());

        Coffee milkCoffee = new MilkDecorator(coffee);
        System.out.println(milkCoffee.description() + " $" + milkCoffee.cost());

        Coffee milkSugarCoffee = new SugarDecorator(milkCoffee);
        System.out.println(milkSugarCoffee.description() + " $" + milkSugarCoffee.cost());
    }
}
输出:
Simple Coffee $2.0
Simple Coffee, Milk $2.5
Simple Coffee, Milk, Sugar $2.7
说明:
  • 装饰器模式适用于需要在运行时动态添加功能的场景。
  • 相比继承,装饰器模式更加灵活,可以在不同对象上添加不同的功能。

9. 外观模式(Facade Pattern)

外观模式为子系统中的一组接口提供一个统一的接口,简化高层模块对子系统的使用。它适用于需要简化复杂接口调用的场景,例如启动系统、关闭系统等。

代码示例:
// 子系统类 1
class CPU {
    public void start() {
        System.out.println("CPU started");
    }
}

// 子系统类 2
class Memory {
    public void load() {
        System.out.println("Memory loaded");
    }
}

// 子系统类 3
class HardDrive {
    public void read() {
        System.out.println("HardDrive read");
    }
}

// 外观类
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        cpu = new CPU();
        memory = new Memory();
        hardDrive = new HardDrive();
    }

    public void startComputer() {
        cpu.start();
        memory.load();
        hardDrive.read();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.startComputer();
    }
}
输出:
CPU started
Memory loaded
HardDrive read
说明:
  • 外观模式适用于需要简化复杂系统调用的场景。
  • 提供统一的接口,使得客户端无需了解子系统的细节。

10. 组合模式(Composite Pattern)

组合模式允许将对象组合成树形结构,以表示“部分-整体”的层次结构。它适用于需要处理树形结构的场景,例如文件系统、菜单结构等。

代码示例:
// 抽象组件
interface Component {
    void showPrice();
}

// 叶子节点
class Leaf implements Component {
    private int price;
    private String name;

    public Leaf(int price, String name) {
        this.price = price;
        this.name = name;
    }

    @Override
    public void showPrice() {
        System.out.println(name + " : " + price);
    }
}

// 容器节点
class Composite implements Component {
    private List<Component> components = new ArrayList<>();
    private String name;

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

    public void addComponent(Component component) {
        components.add(component);
    }

    @Override
    public void showPrice() {
        System.out.println(name);
        for (Component component : components) {
            component.showPrice();
        }
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Leaf leaf1 = new Leaf(10, "Leaf 1");
        Leaf leaf2 = new Leaf(20, "Leaf 2");

        Composite composite = new Composite("Composite 1");
        composite.addComponent(leaf1);
        composite.addComponent(leaf2);

        composite.showPrice();
    }
}
输出:
Composite 1
Leaf 1 : 10
Leaf 2 : 20
说明:
  • 组合模式适用于需要处理树形结构的场景。
  • 可以递归地处理对象,使客户端无需区分叶子节点和容器节点。

11. 桥接模式(Bridge Pattern)

桥接模式将抽象部分与其实现部分分离,使它们可以独立变化。它适用于需要解耦两个独立变化的维度的场景,例如不同操作系统上的图形库、不同支付方式的不同支付渠道等。

代码示例:
// 实现接口
interface Implementor {
    void operationImpl();
}

// 具体实现类 A
class ConcreteImplementorA implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorA operation");
    }
}

// 具体实现类 B
class ConcreteImplementorB implements Implementor {
    @Override
    public void operationImpl() {
        System.out.println("ConcreteImplementorB operation");
    }
}

// 抽象类
abstract class Abstraction {
    protected Implementor implementor;

    protected Abstraction(Implementor implementor) {
        this.implementor = implementor;
    }

    abstract void operation();
}

// 扩展抽象类
class RefinedAbstraction extends Abstraction {
    public RefinedAbstraction(Implementor implementor) {
        super(implementor);
    }

    @Override
    void operation() {
        System.out.println("RefinedAbstraction operation");
        implementor.operationImpl();
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Implementor implementorA = new ConcreteImplementorA();
        Implementor implementorB = new ConcreteImplementorB();

        Abstraction abstraction1 = new RefinedAbstraction(implementorA);
        Abstraction abstraction2 = new RefinedAbstraction(implementorB);

        abstraction1.operation();
        abstraction2.operation();
    }
}
输出:
RefinedAbstraction operation
ConcreteImplementorA operation
RefinedAbstraction operation
ConcreteImplementorB operation
说明:
  • 桥接模式适用于需要解耦两个独立变化维度的场景。
  • 通过桥接,可以避免类爆炸的问题,提高系统的可扩展性。

12. 享元模式(Flyweight Pattern)

享元模式通过共享对象来减少内存使用,适用于大量相似对象的场景,例如字符串池、数据库连接池等。

代码示例:
// 享元接口
interface Flyweight {
    void operation(String externalState);
}

// 具体享元类
class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String externalState) {
        System.out.println("Intrinsic State: " + intrinsicState + ", External State: " + externalState);
    }
}

// 享元工厂
class FlyweightFactory {
    private Map<String, Flyweight> flyweights = new HashMap<>();

    public Flyweight getFlyweight(String key) {
        if (!flyweights.containsKey(key)) {
            flyweights.put(key, new ConcreteFlyweight(key));
        }
        return flyweights.get(key);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        Flyweight flyweight1 = factory.getFlyweight("A");
        flyweight1.operation("External State 1");

        Flyweight flyweight2 = factory.getFlyweight("A");
        flyweight2.operation("External State 2");

        Flyweight flyweight3 = factory.getFlyweight("B");
        flyweight3.operation("External State 3");
    }
}
输出:
Intrinsic State: A, External State: External State 1
Intrinsic State: A, External State: External State 2
Intrinsic State: B, External State: External State 3
说明:
  • 享元模式适用于需要减少内存使用的场景。
  • 通过共享对象,可以减少重复创建对象的开销。

三、行为型模式

行为型模式关注对象之间的交互和职责分配。常见的行为型模式包括:观察者模式、策略模式、责任链模式、命令模式、状态模式、模板方法模式和访问者模式

13. 观察者模式(Observer Pattern)

观察者模式定义对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知并自动更新。它适用于需要通知多个对象的场景,例如事件监听、数据绑定等。

代码示例:
// 主题接口
interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 观察者接口
interface Observer {
    void update(String message);
}

// 具体主题类
class NewsAgency implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private String news;

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(news);
        }
    }

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

// 具体观察者类
class NewsChannel implements Observer {
    private String news;

    @Override
    public void update(String message) {
        this.news = message;
        System.out.println("NewsChannel received: " + news);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        NewsAgency agency = new NewsAgency();
        NewsChannel channel1 = new NewsChannel();
        NewsChannel channel2 = new NewsChannel();

        agency.registerObserver(channel1);
        agency.registerObserver(channel2);

        agency.setNews("Breaking News: Java 17 Released!");
    }
}
输出:
NewsChannel received: Breaking News: Java 17 Released!
NewsChannel received: Breaking News: Java 17 Released!
说明:
  • 观察者模式适用于需要通知多个对象的场景。
  • 主题和观察者之间解耦,提高系统的灵活性。

14. 策略模式(Strategy Pattern)

策略模式定义一系列算法,将每个算法封装起来,并使它们可以互换使用。它适用于需要在运行时选择不同算法的场景,例如支付方式、排序算法等。

代码示例:
// 策略接口
interface Strategy {
    int doOperation(int num1, int num2);
}

// 具体策略类 1
class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

// 具体策略类 2
class OperationSubtract implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

// 上下文类
class Context {
    private Strategy strategy;

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

    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Context context = new Context(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new OperationSubtract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
    }
}
输出:
10 + 5 = 15
10 - 5 = 5
说明:
  • 策略模式适用于需要在运行时选择不同算法的场景。
  • 将算法封装在独立的类中,便于扩展和维护。

15. 责任链模式(Chain of Responsibility Pattern)

责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。它适用于需要多个对象依次处理请求的场景,例如审批流程、过滤器链等。

代码示例:
// 请求类
class Request {
    private int amount;

    public Request(int amount) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }
}

// 抽象处理者
abstract class Handler {
    protected Handler nextHandler;

    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public abstract void handleRequest(Request request);
}

// 具体处理者 1
class TeamLeader extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getAmount() <= 1000) {
            System.out.println("TeamLeader approved the request of $" + request.getAmount());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理者 2
class Manager extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getAmount() <= 5000) {
            System.out.println("Manager approved the request of $" + request.getAmount());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 具体处理者 3
class Director extends Handler {
    @Override
    public void handleRequest(Request request) {
        if (request.getAmount() > 5000) {
            System.out.println("Director approved the request of $" + request.getAmount());
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Handler teamLeader = new TeamLeader();
        Handler manager = new Manager();
        Handler director = new Director();

        teamLeader.setNextHandler(manager);
        manager.setNextHandler(director);

        Request request1 = new Request(800);
        teamLeader.handleRequest(request1);

        Request request2 = new Request(3000);
        teamLeader.handleRequest(request2);

        Request request3 = new Request(10000);
        teamLeader.handleRequest(request3);
    }
}
输出:
TeamLeader approved the request of $800
Manager approved the request of $3000
Director approved the request of $10000
说明:
  • 责任链模式适用于需要多个对象依次处理请求的场景。
  • 通过链式调用,可以动态调整处理流程。

16. 命令模式(Command Pattern)

命令模式将请求封装为对象,从而使您可以使用不同的请求、队列或日志来参数化其他对象。它适用于需要记录操作、撤销/重做、事务回滚的场景。

代码示例:
// 命令接口
interface Command {
    void execute();
}

// 接收者类
class Light {
    public void on() {
        System.out.println("Light is on");
    }

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

// 具体命令类 1
class LightOnCommand implements Command {
    private Light light;

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

    @Override
    public void execute() {
        light.on();
    }
}

// 具体命令类 2
class LightOffCommand implements Command {
    private Light light;

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

    @Override
    public void execute() {
        light.off();
    }
}

// 调用者类
class RemoteControl {
    private Command command;

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

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

// 使用示例
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();
    }
}
输出:
Light is on
Light is off
说明:
  • 命令模式适用于需要封装请求的场景。
  • 可用于实现撤销/重做、事务回滚等功能。

17. 状态模式(State Pattern)

状态模式允许对象在其内部状态改变时改变其行为。它适用于对象的行为依赖于其状态的场景,例如订单状态、游戏角色状态等。

代码示例:
// 状态接口
interface State {
    void doAction(Context context);
}

// 具体状态类 1
class StartState implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("Player is in start state");
        context.setState(this);
    }

    public String toString() {
        return "Start State";
    }
}

// 具体状态类 2
class StopState implements State {
    @Override
    public void doAction(Context context) {
        System.out.println("Player is in stop state");
        context.setState(this);
    }

    public String toString() {
        return "Stop State";
    }
}

// 上下文类
class Context {
    private State state;

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

    public State getState() {
        return state;
    }

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

// 使用示例
public class Main {
    public static void main(String[] args) {
        Context context = new Context();

        State startState = new StartState();
        startState.doAction(context);
        System.out.println("Current state: " + context.getState());

        State stopState = new StopState();
        stopState.doAction(context);
        System.out.println("Current state: " + context.getState());
    }
}
输出:
Player is in start state
Current state: Start State
Player is in stop state
Current state: Stop State
说明:
  • 状态模式适用于对象的行为依赖于其状态的场景。
  • 通过状态对象的变化,可以动态改变对象的行为。

18. 模板方法模式(Template Method Pattern)

模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中。它适用于需要定义算法框架、但允许子类重写某些步骤的场景,例如测试框架、游戏关卡设计等。

代码示例:
// 抽象类
abstract class Game {
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();

    // 模板方法
    public final void play() {
        initialize();
        startPlay();
        endPlay();
    }
}

// 具体类 1
class Cricket extends Game {
    @Override
    void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }

    @Override
    void endPlay() {
        System.out.println("Cricket Game Finished!");
    }
}

// 具体类 2
class Football extends Game {
    @Override
    void initialize() {
        System.out.println("Football Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Football Game Started. Enjoy the game!");
    }

    @Override
    void endPlay() {
        System.out.println("Football Game Finished!");
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Game game = new Cricket();
        game.play();

        System.out.println();

        game = new Football();
        game.play();
    }
}
输出:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
说明:
  • 模板方法模式适用于定义算法框架的场景。
  • 子类可以重写部分步骤,但不能改变算法的整体结构。

19. 访问者模式(Visitor Pattern)

访问者模式允许在不修改对象结构的情况下,定义作用于对象的新操作。它适用于需要对一组对象进行不同操作的场景,例如报表生成、数据导出等。

代码示例:
// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素类
class ConcreteElementA implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementA(this);
    }

    public String operationA() {
        return "ConcreteElementA";
    }
}

class ConcreteElementB implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitConcreteElementB(this);
    }

    public String operationB() {
        return "ConcreteElementB";
    }
}

// 访问者接口
interface Visitor {
    void visitConcreteElementA(ConcreteElementA element);
    void visitConcreteElementB(ConcreteElementB element);
}

// 具体访问者类
class ConcreteVisitor implements Visitor {
    @Override
    public void visitConcreteElementA(ConcreteElementA element) {
        System.out.println("Visited " + element.operationA());
    }

    @Override
    public void visitConcreteElementB(ConcreteElementB element) {
        System.out.println("Visited " + element.operationB());
    }
}

// 对象结构类
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();

    public void attach(Element element) {
        elements.add(element);
    }

    public void detach(Element element) {
        elements.remove(element);
    }

    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();
        structure.attach(new ConcreteElementA());
        structure.attach(new ConcreteElementB());

        Visitor visitor = new ConcreteVisitor();
        structure.accept(visitor);
    }
}
输出:
Visited ConcreteElementA
Visited ConcreteElementB
说明:
  • 访问者模式适用于需要对一组对象执行不同操作的场景。
  • 通过访问者,可以将操作与对象结构分离,提高系统的扩展性。

四、总结与最佳实践

设计模式是软件开发中解决常见问题的经典方案,它们提供了一种可重用的、经过验证的代码结构,使得程序更加灵活、可扩展,并且易于维护。Java 作为一门面向对象的编程语言,广泛支持各种设计模式的应用。

在实际开发中,合理使用设计模式可以提高代码的可读性、可维护性和可扩展性。然而,设计模式并非万能钥匙,过度使用或错误使用设计模式可能会导致代码复杂化,影响性能和可维护性。因此,在使用设计模式时,应遵循以下最佳实践:

  1. 理解设计模式的本质:设计模式是解决特定问题的通用方案,不应盲目套用。应根据实际需求选择合适的模式。
  2. 避免过度设计:在项目初期,应优先考虑简单、直接的解决方案,只有在遇到复杂问题时才引入设计模式。
  3. 结合业务场景:设计模式应服务于业务需求,而非为了使用模式而使用模式。应根据实际业务逻辑选择合适的模式。
  4. 保持代码简洁:即使使用了设计模式,也应保持代码的简洁性,避免不必要的复杂性。
  5. 测试设计模式的实现:设计模式的实现应经过充分的测试,确保其符合预期,并不会引入新的问题。
  6. 文档化设计模式的使用:在团队协作中,应记录设计模式的使用方式,以便其他开发者理解和维护代码。

通过合理使用设计模式,可以提高代码的质量,使系统更加灵活、可扩展,并且易于维护。希望本博客能够帮助读者深入理解 Java 设计模式,并在实际项目中灵活应用这些模式,提高软件开发的效率和质量。


网站公告

今日签到

点亮在社区的每一天
去签到