常用设计模式学习

23 种设计模式可以分为 三大类, 分别是 创建型结构型行为型


1)创建型模式(Creational Patterns):

用于创建对象的模式,同时隐藏对象创建的逻辑,避免代码中出现大量new操作和复杂的创建逻辑。目的是解耦对象的创建和使用。

  • 常用的有:单例模式、工厂模式、建造者模式。
  • 不常见的有:原型模式。

2)结构型模式(Structural Patterns):

用于处理对象组合的结构,关注类与对象的组合。目的是通过组合对象或类的方式,形成更大的结构。

  • 常用的有:适配器模式、桥接模式、组合模式、装饰器模式、代理模式。
  • 不常见的有:外观模式(门面模式)、享元模式。

3)行为型模式(Behavioral Patterns):

用于定义对象如何相互协作以完成单个对象无法单独实现的任务,目的是定义类和对象间的通信方式。

  • 常用的有:观察者模式、责任链模式、策略模式、模板模式、状态模式、迭代器模式。
  • 不常见的有:备忘录模式、命令模式、中介者模式、访问者模式、解释器模式。

创建型模式:

单例模式

业务场景:数据库连接池、线程池

特点:

1、唯一性:类的实例在整个程序生命周期内只存在一个。
2、全局访问:提供一个全局访问点,让所有代码可以访问同一个实例。
3、延迟加载:可以延迟实例化,在需要时才创建实例(如使用懒汉式实现)。

示例:多种单例实现

  • 饿汉式:简单安全但可能浪费资源
  • 双重检查锁:延迟加载且线程安全
  • 静态内部类:推荐的标准实现方式
  • 枚举实现:最安全的实现(防止反射和序列化攻击)
import java.io.Serializable;

/**
 * 单例模式多种实现方式演示
 */
public class SingletonDemo {

    //------------------------- 饿汉式 -------------------------
    /**
     * 饿汉式(线程安全,类加载时初始化)
     * 优点:实现简单,线程安全
     * 缺点:可能造成资源浪费(如果实例未被使用)
     */
    static class EagerSingleton {
        private static final EagerSingleton INSTANCE = new EagerSingleton();

        private EagerSingleton() {
            // 防止反射创建实例
            if (INSTANCE != null) {
                throw new IllegalStateException("单例实例已存在");
            }
        }

        public static EagerSingleton getInstance() {
            return INSTANCE;
        }
    }

    //------------------------- 懒汉式(双重检查锁) -------------------------
    /**
     * 双重检查锁(DCL)实现(延迟加载,线程安全)
     * 优点:延迟初始化,节省资源
     * 注意:需要volatile防止指令重排序
     */
    static class LazySingleton {
        private static volatile LazySingleton INSTANCE;

        private LazySingleton() {}

        public static LazySingleton getInstance() {
            if (INSTANCE == null) {
                synchronized (LazySingleton.class) {
                    if (INSTANCE == null) {
                        INSTANCE = new LazySingleton();
                    }
                }
            }
            return INSTANCE;
        }
    }

    //------------------------- 静态内部类 -------------------------
    /**
     * 静态内部类实现(推荐方式)
     * 优点:兼顾线程安全和延迟加载
     * 原理:利用类加载机制保证线程安全
     */
    static class InnerClassSingleton {
        private InnerClassSingleton() {}

        private static class Holder {
            static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
        }

        public static InnerClassSingleton getInstance() {
            return Holder.INSTANCE;
        }
    }

    //------------------------- 枚举实现(最佳实践) -------------------------
    /**
     * 枚举实现(Effective Java推荐方式)
     * 优点:防止反射攻击,自动处理序列化
     * 缺点:无法延迟初始化
     */
    enum EnumSingleton {
        INSTANCE;

        public void doSomething() {
            System.out.println("枚举单例方法执行");
        }
    }

    //------------------------- 防止序列化破坏的单例 -------------------------
    /**
     * 可序列化的安全单例
     * 注意:需要添加readResolve方法防止反序列化创建新实例
     */
    static class SerializableSingleton implements Serializable {
        private static final long serialVersionUID = 1L;
        private static final SerializableSingleton INSTANCE = new SerializableSingleton();

        private SerializableSingleton() {}

        public static SerializableSingleton getInstance() {
            return INSTANCE;
        }

        // 关键方法:防止反序列化创建新实例
        private Object readResolve() {
            return INSTANCE;
        }
    }

    //------------------------- 测试代码 -------------------------
    public static void main(String[] args) {
        // 测试饿汉式
        EagerSingleton eager1 = EagerSingleton.getInstance();
        EagerSingleton eager2 = EagerSingleton.getInstance();
        System.out.println("饿汉式单例测试: " + (eager1 == eager2)); // true

        // 测试双重检查锁
        LazySingleton lazy1 = LazySingleton.getInstance();
        LazySingleton lazy2 = LazySingleton.getInstance();
        System.out.println("双重检查锁测试: " + (lazy1 == lazy2)); // true

        // 测试静态内部类
        InnerClassSingleton inner1 = InnerClassSingleton.getInstance();
        InnerClassSingleton inner2 = InnerClassSingleton.getInstance();
        System.out.println("静态内部类测试: " + (inner1 == inner2)); // true

        // 测试枚举单例
        EnumSingleton.INSTANCE.doSomething();
        System.out.println("枚举单例测试: " + (EnumSingleton.INSTANCE == EnumSingleton.INSTANCE)); // true

        // 测试序列化安全单例
        SerializableSingleton serial1 = SerializableSingleton.getInstance();
        SerializableSingleton serial2 = SerializableSingleton.getInstance();
        System.out.println("序列化安全测试: " + (serial1 == serial2)); // true
    }
}

示例:数据库连接池:

在项目中,数据库连接池通常只需要一个实例来管理所有的数据库连接,避免频繁创建和销毁连接。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class ConnectionPool {
    private static final int POOL_SIZE = 10;
    private static ConnectionPool instance;
    private List<Connection> connectionPool;

    private ConnectionPool() {
        connectionPool = new ArrayList<>(POOL_SIZE);
        initializePool();
    }

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

    private void initializePool() {
        for (int i = 0; i < POOL_SIZE; i++) {
            try {
                Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
                connectionPool.add(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized Connection getConnection() {
        if (connectionPool.isEmpty()) {
            throw new RuntimeException("No available connections in the pool");
        }
        return connectionPool.remove(connectionPool.size() - 1);
    }

    /**
     * 将连接归还到连接池中
     * @param connection 当前连接
     */
    public synchronized void releaseConnection(Connection connection) {
        connectionPool.add(connection);
    }
}

工厂方法模式

业务场景:日志记录器

示例:日志记录器

此实现遵循开闭原则(对扩展开放,对修改关闭),能够很好地应对日志记录需求的变化。

// 步骤1:定义日志记录器接口
interface Logger {
    /**
     * 记录日志的方法
     * @param message 要记录的日志信息
     */
    void log(String message);
}

// 步骤2:实现具体日志记录器
class FileLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("文件日志记录: " + message);
    }
}

class DatabaseLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("数据库日志记录: " + message);
    }
}

class ConsoleLogger implements Logger {
    @Override
    public void log(String message) {
        System.out.println("控制台日志记录: " + message);
    }
}

// 步骤3:定义日志记录器工厂接口
interface LoggerFactory {
    /**
     * 创建日志记录器的工厂方法
     * @return 具体的日志记录器实例
     */
    Logger createLogger();
}

// 步骤4:实现具体工厂类
class FileLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可以在此处添加文件日志记录器特有的初始化逻辑
        return new FileLogger();
    }
}

class DatabaseLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 可以在此处添加数据库连接等初始化逻辑
        return new DatabaseLogger();
    }
}

class ConsoleLoggerFactory implements LoggerFactory {
    @Override
    public Logger createLogger() {
        // 控制台记录器通常不需要特殊初始化
        return new ConsoleLogger();
    }
}

// 步骤5:客户端使用示例
public class LoggerClient {
    public static void main(String[] args) {
        // 使用文件日志工厂
        LoggerFactory fileFactory = new FileLoggerFactory();
        Logger fileLogger = fileFactory.createLogger();
        fileLogger.log("这是一个测试日志");
        
        // 使用数据库日志工厂
        LoggerFactory dbFactory = new DatabaseLoggerFactory();
        Logger dbLogger = dbFactory.createLogger();
        dbLogger.log("用户登录成功");
        
        // 使用控制台日志工厂
        LoggerFactory consoleFactory = new ConsoleLoggerFactory();
        Logger consoleLogger = consoleFactory.createLogger();
        consoleLogger.log("系统启动完成");
    }
}
文件日志记录: 这是一个测试日志
数据库日志记录: 用户登录成功
控制台日志记录: 系统启动完成

建造者模式

业务场景:复杂对象的构造(HTML文档生成器)、链式调用(构建一个 HTTP 请求对象)

示例:HTML文档生成器

当对象的构造过程非常复杂,包含多个步骤或参数时,建造者模式可以帮助简化构造逻辑。

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

/**
 * 产品类:HTML文档
 */
class HtmlDocument {
    private String headTitle;       // 头部标题
    private List<String> bodyElements = new ArrayList<>(); // 主体元素集合

    /**
     * 添加头部标题
     * @param title 标题文本
     */
    public void setHeadTitle(String title) {
        this.headTitle = title;
    }

    /**
     * 向主体添加元素
     * @param element HTML元素字符串
     */
    public void addBodyElement(String element) {
        bodyElements.add(element);
    }

    /**
     * 生成完整HTML文档字符串
     * @return 格式化后的HTML内容
     */
    public String generate() {
        StringBuilder sb = new StringBuilder();
        sb.append("<html>\n");
        sb.append("<head>\n");
        sb.append("<title>").append(headTitle).append("</title>\n");
        sb.append("</head>\n");
        sb.append("<body>\n");
        for (String element : bodyElements) {
            sb.append("  ").append(element).append("\n");
        }
        sb.append("</body>\n");
        sb.append("</html>");
        return sb.toString();
    }
}

/**
 * 抽象建造者接口
 */
interface HtmlBuilder {
    // 构建头部
    void buildHeader(String title);
    
    // 构建正文段落
    void addParagraph(String text);
    
    // 构建无序列表
    void addUnorderedList(List<String> items);
    
    // 构建水平线
    void addHorizontalRule();
    
    // 获取生成结果
    HtmlDocument getResult();
}

/**
 * 具体建造者:HTML文档生成器
 */
class HtmlDocumentBuilder implements HtmlBuilder {
    private HtmlDocument document = new HtmlDocument();

    @Override
    public void buildHeader(String title) {
        document.setHeadTitle(title);
    }

    @Override
    public void addParagraph(String text) {
        String element = "<p>" + text + "</p>";
        document.addBodyElement(element);
    }

    @Override
    public void addUnorderedList(List<String> items) {
        StringBuilder sb = new StringBuilder("<ul>\n");
        for (String item : items) {
            sb.append("  <li>").append(item).append("</li>\n");
        }
        sb.append("</ul>");
        document.addBodyElement(sb.toString());
    }

    @Override
    public void addHorizontalRule() {
        document.addBodyElement("<hr/>");
    }

    @Override
    public HtmlDocument getResult() {
        return document;
    }
}

/**
 * 指挥者(可选):封装常用构建流程
 */
class DocumentDirector {
    public HtmlDocument buildReportDocument(HtmlBuilder builder) {
        builder.buildHeader("销售报告");
        builder.addParagraph("2025年度销售汇总:");
        
        List<String> data = List.of("第一季度:¥1,200万", 
                                  "第二季度:¥1,500万",
                                  "第三季度:¥1,800万");
        builder.addUnorderedList(data);
        builder.addHorizontalRule();
        builder.addParagraph("数据截止日期:2025-12-31");
        return builder.getResult();
    }
}

/**
 * 客户端使用示例
 */
public class HtmlGeneratorClient {
    public static void main(String[] args) {
        // 方式1:直接使用建造者
        HtmlBuilder builder = new HtmlDocumentBuilder();
        builder.buildHeader("欢迎页面");
        builder.addParagraph("欢迎访问我们的网站!");
        builder.addHorizontalRule();
        HtmlDocument doc1 = builder.getResult();
        System.out.println("简单页面:\n" + doc1.generate());

        // 方式2:通过指挥者构建
        DocumentDirector director = new DocumentDirector();
        HtmlDocument reportDoc = director.buildReportDocument(new HtmlDocumentBuilder());
        System.out.println("\n报告文档:\n" + reportDoc.generate());
    }
}
简单页面:
<html>
<head>
<title>欢迎页面</title>
</head>
<body>
  <p>欢迎访问我们的网站!</p>
  <hr/>
</body>
</html>

报告文档:
<html>
<head>
<title>销售报告</title>
</head>
<body>
  <p>2025年度销售汇总:</p>
  <ul>
  <li>第一季度:¥1,200万</li>
  <li>第二季度:¥1,500万</li>
  <li>第三季度:¥1,800万</li>
</ul>
  <hr/>
  <p>数据截止日期:2025-12-31</p>
</body>
</html>

结构型模式:

适配器模式

业务场景:旧系统的兼容升级

在实际业务中推荐优先使用对象适配器

  1. 符合组合优于继承的原则
  2. 更易扩展和维护
  3. 可以适配多个不同的旧系统组件
  4. 不会破坏原有继承体系

示例:旧系统日志记录器升级

特性类适配器对象适配器
实现方式继承旧类组合旧类对象
灵活性只能适配一个父类可以适配多个不同类
旧系统方法覆盖可以直接覆盖需要通过委托调用
耦合度较高(继承关系)较低(对象组合)
推荐使用场景当需要完全重写部分旧逻辑时需要保持旧系统完整性的情况
import java.time.LocalDateTime;

/**
 * 旧系统日志记录器(需要适配的类)
 */
class LegacyLogger {
    /**
     * 旧版日志记录方法
     * @param severity 日志级别(1:信息 2:警告 3:错误)
     * @param timestamp 时间戳(旧格式:字符串)
     * @param message 日志内容
     */
    public void log(int severity, String timestamp, String message) {
        System.out.printf("[%s][%d] %s\n", timestamp, severity, message);
    }
}

/**
 * 新系统日志接口(目标接口)
 */
interface ModernLogger {
    void info(String message);
    void warn(String message);
    void error(String message);
}

/**
 * 类适配器(通过继承实现适配)
 */
class ClassLoggerAdapter extends LegacyLogger implements ModernLogger {
    @Override
    public void info(String message) {
        super.log(1, LocalDateTime.now().toString(), "[INFO] " + message);
    }

    @Override
    public void warn(String message) {
        super.log(2, LocalDateTime.now().toString(), "[WARN] " + message);
    }

    @Override
    public void error(String message) {
        super.log(3, LocalDateTime.now().toString(), "[ERROR] " + message);
    }
}

/**
 * 对象适配器(通过组合实现适配)
 */
class ObjectLoggerAdapter implements ModernLogger {
    private LegacyLogger legacyLogger;

    public ObjectLoggerAdapter(LegacyLogger legacyLogger) {
        this.legacyLogger = legacyLogger;
    }

    @Override
    public void info(String message) {
        legacyLogger.log(1, LocalDateTime.now().toString(), "[INFO] " + message);
    }

    @Override
    public void warn(String message) {
        legacyLogger.log(2, LocalDateTime.now().toString(), "[WARN] " + message);
    }

    @Override
    public void error(String message) {
        legacyLogger.log(3, LocalDateTime.now().toString(), "[ERROR] " + message);
    }
}

/**
 * 新增的现代日志实现(用于对比)
 */
class ModernLoggerImpl implements ModernLogger {
    @Override
    public void info(String message) {
        System.out.printf("%s [INFO] %s\n", LocalDateTime.now(), message);
    }

    @Override
    public void warn(String message) {
        System.out.printf("%s [WARN] %s\n", LocalDateTime.now(), message);
    }

    @Override
    public void error(String message) {
        System.out.printf("%s [ERROR] %s\n", LocalDateTime.now(), message);
    }
}

/**
 * 客户端使用示例
 */
public class LoggerClient {
    public static void main(String[] args) {
        // 旧系统直接调用
        LegacyLogger oldLogger = new LegacyLogger();
        oldLogger.log(1, "2023-08-25T10:00:00", "System started");

        // 使用类适配器
        ModernLogger classAdapter = new ClassLoggerAdapter();
        classAdapter.info("System initialized");
        classAdapter.warn("Memory usage high");
        classAdapter.error("Disk full!");

        System.out.println("------------------------");

        // 使用对象适配器
        ModernLogger objectAdapter = new ObjectLoggerAdapter(new LegacyLogger());
        objectAdapter.info("New user registered");
        objectAdapter.warn("API response slow");
        objectAdapter.error("Database connection failed");

        System.out.println("------------------------");

        // 现代实现
        ModernLogger modern = new ModernLoggerImpl();
        modern.info("Modern system ready");
        modern.error("Critical failure detected");
    }
}
[2023-08-25T10:00:00][1] System started
[2025-03-07T14:05:09.222224400][1] [INFO] System initialized
[2025-03-07T14:05:09.224219900][2] [WARN] Memory usage high
[2025-03-07T14:05:09.224219900][3] [ERROR] Disk full!
------------------------
[2025-03-07T14:05:09.225217700][1] [INFO] New user registered
[2025-03-07T14:05:09.225217700][2] [WARN] API response slow
[2025-03-07T14:05:09.226239700][3] [ERROR] Database connection failed
------------------------
2025-03-07T14:05:09.227237400 [INFO] Modern system ready
2025-03-07T14:05:09.227237400 [ERROR] Critical failure detected

装饰器模式

业务场景:动态为对象增加功能,如 Java IO 流

示例:咖啡订单系统

基础咖啡可以动态添加配料(装饰器),类似Java IO流层层包装的思想。

/**
 * 装饰器模式示例:咖啡订单系统
 * 关键结构:
 * 1. 组件接口(Component)
 * 2. 具体组件(ConcreteComponent)
 * 3. 装饰器基类(Decorator)
 * 4. 具体装饰器(ConcreteDecorator)
 */

// 1. 组件接口:定义咖啡的基本操作
interface Coffee {
    String getDescription(); // 获取描述
    double getCost();         // 获取价格
}

// 2. 具体组件:基础咖啡
class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() {
        return "基础咖啡";
    }

    @Override
    public double getCost() {
        return 10.0;
    }
}

// 3. 装饰器基类(实现组件接口,并持有组件引用)
abstract class CoffeeDecorator implements Coffee {
    protected Coffee decoratedCoffee; // 被装饰的咖啡对象

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

    // 默认直接转发给被装饰对象
    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription();
    }

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

// 4. 具体装饰器:牛奶装饰器
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription() + " + 牛奶";
    }

    @Override
    public double getCost() {
        return decoratedCoffee.getCost() + 2.5;
    }
}

// 4. 具体装饰器:糖浆装饰器
class SyrupDecorator extends CoffeeDecorator {
    public SyrupDecorator(Coffee coffee) {
        super(coffee);
    }

    @Override
    public String getDescription() {
        return decoratedCoffee.getDescription() + " + 糖浆";
    }

    @Override
    public double getCost() {
        return decoratedCoffee.getCost() + 1.8;
    }
}

// 客户端使用示例
public class DecoratorPatternDemo {
    public static void main(String[] args) {
        // 基础咖啡
        Coffee coffee = new SimpleCoffee();
        System.out.println("基础咖啡:" + coffee.getDescription() 
                          + ",价格:" + coffee.getCost());

        // 添加牛奶
        Coffee milkCoffee = new MilkDecorator(coffee);
        System.out.println("加料咖啡:" + milkCoffee.getDescription() 
                          + ",价格:" + milkCoffee.getCost());

        // 添加牛奶+糖浆(多层装饰)
        Coffee sweetMilkCoffee = new SyrupDecorator(milkCoffee);
        System.out.println("加料咖啡:" + sweetMilkCoffee.getDescription() 
                          + ",价格:" + sweetMilkCoffee.getCost());
    }
}
基础咖啡:基础咖啡,价格:10.0
加料咖啡:基础咖啡 + 牛奶,价格:12.5
加料咖啡:基础咖啡 + 牛奶 + 糖浆,价格:14.3

代理模式

业务场景:实现访问控制,如 RPC 调用

示例:敏感操作访问控制(保护代理)

控制访问,增强非业务功能(权限/日志),通常在编译期确定关系,可能隐藏真实对象创建过程

/**
 * 代理模式示例:敏感操作访问控制(保护代理)
 * 关键结构:
 * 1. 服务接口(Subject)
 * 2. 真实服务(RealSubject)
 * 3. 代理类(Proxy)
 */

// 1. 服务接口:定义敏感操作
interface DataService {
    void deleteData(String dataId, String userRole) throws Exception;
}

// 2. 真实服务:实际执行数据删除
class RealDataService implements DataService {
    @Override
    public void deleteData(String dataId, String userRole) {
        System.out.println("正在删除数据:" + dataId);
        // 真实数据库删除操作...
    }
}

// 3. 代理类:控制访问权限
class DataServiceProxy implements DataService {
    private RealDataService realService = new RealDataService();

    @Override
    public void deleteData(String dataId, String userRole) throws Exception {
        // 前置权限校验
        if (!"admin".equals(userRole)) {
            throw new Exception("权限不足:需要管理员权限执行删除操作");
        }
        
        // 权限校验通过后调用真实服务
        realService.deleteData(dataId, userRole);
        
        // 后置日志记录(扩展功能)
        System.out.println("[操作日志] 用户角色:" + userRole + " 删除了数据:" + dataId);
    }
}

// 客户端使用示例
public class ProxyPatternDemo {
    public static void main(String[] args) {
        DataService service = new DataServiceProxy();
        
        try {
            // 管理员操作(允许执行)
            service.deleteData("20230815_001", "admin");
            
            // 普通用户操作(会被拦截)
            service.deleteData("20230815_002", "user");
        } catch (Exception e) {
            System.out.println("操作异常:" + e.getMessage());
        }
    }
}
正在删除数据:20230815_001
[操作日志] 用户角色:admin 删除了数据:20230815_001
操作异常:权限不足:需要管理员权限执行删除操作

行为型模式:

观察者模式

业务场景:事件驱动系统,如 订阅 - 发布 系统

示例:模拟气象站数据更新通知多个显示板的场景

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

// 主题接口(被观察对象)
interface WeatherSubject {
    void registerObserver(WeatherObserver o); // 注册观察者
    void removeObserver(WeatherObserver o);  // 移除观察者
    void notifyObservers();                  // 通知观察者
}

// 观察者接口
interface WeatherObserver {
    void update(float temperature, float humidity, float pressure); // 更新方法
}

// 具体主题:气象数据站
class WeatherStation implements WeatherSubject {
    private List<WeatherObserver> observers = new ArrayList<>();
    private float temperature;
    private float humidity;
    private float pressure;

    // 注册观察者
    @Override
    public void registerObserver(WeatherObserver o) {
        observers.add(o);
    }

    // 移除观察者
    @Override
    public void removeObserver(WeatherObserver o) {
        observers.remove(o);
    }

    // 通知所有观察者
    @Override
    public void notifyObservers() {
        for (WeatherObserver observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    // 更新气象测量数据
    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObservers(); // 数据变化时自动通知观察者
    }
}

// 具体观察者:当前状况显示
class CurrentConditionsDisplay implements WeatherObserver {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.printf("[当前状况] 温度:%.1f℃ 湿度:%.1f%% 气压:%.1fhPa\n", 
                         temperature, humidity, pressure);
    }
}

// 具体观察者:气象统计显示
class StatisticsDisplay implements WeatherObserver {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("[统计显示] 正在更新历史数据...");
        // 这里可以维护温度/湿度/压力的统计信息
    }
}

// 具体观察者:天气预报显示
class ForecastDisplay implements WeatherObserver {
    @Override
    public void update(float temperature, float humidity, float pressure) {
        System.out.println("[天气预报] 根据最新数据生成预测报告...");
        // 这里可以实现天气预报算法
    }
}

// 客户端使用
public class ObserverPatternDemo {
    public static void main(String[] args) {
        // 1. 创建主题对象
        WeatherStation weatherStation = new WeatherStation();
        
        // 2. 创建观察者对象
        WeatherObserver currentDisplay = new CurrentConditionsDisplay();
        WeatherObserver statsDisplay = new StatisticsDisplay();
        WeatherObserver forecastDisplay = new ForecastDisplay();

        // 3. 注册观察者
        weatherStation.registerObserver(currentDisplay);
        weatherStation.registerObserver(statsDisplay);
        weatherStation.registerObserver(forecastDisplay);

        // 4. 模拟气象数据更新(会自动通知所有观察者)
        System.out.println("===== 第一次数据更新 =====");
        weatherStation.setMeasurements(25.5f, 65.0f, 1013.0f);
        
        System.out.println("\n===== 第二次数据更新 =====");
        weatherStation.setMeasurements(26.2f, 68.5f, 1012.5f);

        // 5. 移除一个观察者后再次更新
        System.out.println("\n===== 移除统计显示后的更新 =====");
        weatherStation.removeObserver(statsDisplay);
        weatherStation.setMeasurements(24.8f, 70.0f, 1014.0f);
    }
}
===== 第一次数据更新 =====
[当前状况] 温度:25.5℃ 湿度:65.0% 气压:1013.0hPa
[统计显示] 正在更新历史数据...
[天气预报] 根据最新数据生成预测报告...

===== 第二次数据更新 =====
[当前状况] 温度:26.2℃ 湿度:68.5% 气压:1012.5hPa
[统计显示] 正在更新历史数据...
[天气预报] 根据最新数据生成预测报告...

===== 移除统计显示后的更新 =====
[当前状况] 温度:24.8℃ 湿度:70.0% 气压:1014.0hPa
[天气预报] 根据最新数据生成预测报告...

责任链模式

业务场景:日志级别过滤、请求处理链

示例:请假审批流程

// 抽象处理者角色
abstract class Approver {
    protected Approver nextHandler;

    // 设置下一个处理者
    public void setNext(Approver next) {
        this.nextHandler = next;
    }

    // 处理请求的模板方法
    public abstract boolean approve(int days);
}

// 具体处理者:组长
class GroupLeader extends Approver {
    @Override
    public boolean approve(int days) {
        System.out.println("组长审批:" + days + "天请假");
        if (days <= 1) {
            System.out.println("组长批准申请");
            return true;
        } else {
            System.out.println("组长审批不通过,转交经理");
            return nextHandler != null && nextHandler.approve(days);
        }
    }
}

// 具体处理者:经理
class Manager extends Approver {
    @Override
    public boolean approve(int days) {
        System.out.println("经理审批:" + days + "天请假");
        if (days <= 3) {
            System.out.println("经理批准申请");
            return true;
        } else {
            System.out.println("经理审批不通过,转交总监");
            return nextHandler != null && nextHandler.approve(days);
        }
    }
}

// 具体处理者:总监
class Director extends Approver {
    @Override
    public boolean approve(int days) {
        System.out.println("总监审批:" + days + "天请假");
        if (days <= 5) {
            System.out.println("总监批准申请");
            return true;
        } else {
            System.out.println("总监审批不通过,申请被驳回");
            return false;
        }
    }
}

// 客户端测试代码
public class ChainPatternDemo {
    public static void main(String[] args) {
        // 创建处理链
        Approver groupLeader = new GroupLeader();
        Approver manager = new Manager();
        Approver director = new Director();

        groupLeader.setNext(manager);
        manager.setNext(director);

        // 测试不同请假天数的审批结果
        testApproval(groupLeader, 1);  // 应该通过
        testApproval(groupLeader, 3);  // 应该通过
        testApproval(groupLeader, 4);  // 应该通过
        testApproval(groupLeader, 6);  // 应该被驳回
    }

    private static void testApproval(Approver approver, int days) {
        System.out.println("──────────────");
        boolean result = approver.approve(days);
        System.out.println("审批结果:" + (result ? "通过" : "驳回"));
        System.out.println();
    }
}
──────────────
组长审批:1天请假
组长批准申请
审批结果:通过

──────────────
组长审批:3天请假
组长审批不通过,转交经理
经理审批:3天请假
经理批准申请
审批结果:通过

──────────────
组长审批:4天请假
组长审批不通过,转交经理
经理审批:4天请假
经理审批不通过,转交总监
总监审批:4天请假
总监批准申请
审批结果:通过

──────────────
组长审批:6天请假
组长审批不通过,转交经理
经理审批:6天请假
经理审批不通过,转交总监
总监审批:6天请假
总监审批不通过,申请被驳回
审批结果:驳回

策略模式

业务场景:支付方式选择(如微信、支付宝、信用卡)

示例:支付系统

// 策略接口:定义支付算法的共同接口
interface PaymentStrategy {
    void pay(double amount); // 支付抽象方法
}

// 具体策略类:微信支付
class WeChatPay implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.printf("微信支付成功:%.2f 元\n", amount);
        // 这里可以接入微信支付SDK的具体实现
    }
}

// 具体策略类:支付宝支付
class Alipay implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.printf("支付宝支付成功:%.2f 元\n", amount);
        // 这里可以接入支付宝支付SDK的具体实现
    }
}

// 具体策略类:信用卡支付
class CreditCardPay implements PaymentStrategy {
    private String cardNumber;
    private String cvv;

    public CreditCardPay(String cardNumber, String cvv) {
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }

    @Override
    public void pay(double amount) {
        System.out.printf("信用卡尾号%s支付成功:%.2f 元\n", 
                         cardNumber.substring(15), amount);
        // 这里可以接入银行支付网关的具体实现
    }
}

// 上下文类:负责使用策略
class PaymentProcessor {
    private PaymentStrategy strategy; // 持有策略对象的引用

    // 设置支付策略(关键方法)
    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    // 执行支付操作
    public void executePayment(double amount) {
        if (strategy == null) {
            System.out.println("请先选择支付方式");
            return;
        }
        strategy.pay(amount);
    }
}

// 客户端使用
public class StrategyPatternDemo {
    public static void main(String[] args) {
        // 创建支付处理器(上下文)
        PaymentProcessor processor = new PaymentProcessor();
        
        // 创建不同的支付策略
        PaymentStrategy wechat = new WeChatPay();
        PaymentStrategy alipay = new Alipay();
        PaymentStrategy creditCard = new CreditCardPay("6225880134567890", "123");

        // 使用微信支付
        System.out.println("===== 使用微信支付 =====");
        processor.setPaymentStrategy(wechat);
        processor.executePayment(100.50);

        // 切换支付宝支付
        System.out.println("\n===== 切换支付宝支付 =====");
        processor.setPaymentStrategy(alipay);
        processor.executePayment(200.0);

        // 切换信用卡支付
        System.out.println("\n===== 切换信用卡支付 =====");
        processor.setPaymentStrategy(creditCard);
        processor.executePayment(500.0);
    }
}
===== 使用微信支付 =====
微信支付成功:100.50 元

===== 切换支付宝支付 =====
支付宝支付成功:200.00 元

===== 切换信用卡支付 =====
信用卡尾号0支付成功:500.00 元
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Main12138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值