【Java设计模式实战应用指南:23种设计模式详解】

设计模式是软件开发的最佳实践,掌握设计模式是成为架构师的必经之路。本文将深入剖析常用设计模式的原理和应用场景,助你写出优雅、可维护的代码。

一、设计模式概述

1.1 什么是设计模式?

关键点: 设计模式是在软件开发中反复出现的问题的通用解决方案。

设计模式的六大原则:

  1. 单一职责原则(SRP):一个类只负责一个功能
  2. 开闭原则(OCP):对扩展开放,对修改关闭
    3.里氏替换原则(LSP):子类可以替换父类
  3. 依赖倒置原则(DIP):依赖抽象而非具体
  4. 接口隔离原则(ISP):接口应该小而专
  5. 迪米特法则(LOD):最少知识原则

23种设计模式分类:

  • 创建型模式(5种):单例、工厂、抽象工厂、建造者、原型
  • 结构型模式(7种):适配器、桥接、组合、装饰器、外观、享元、代理
  • 行为型模式(11种):责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者

二、创建型模式

2.1 单例模式(Singleton)

关键点: 确保一个类只有一个实例,并提供全局访问点。

java 复制代码
// ❌ 懒汉式(线程不安全)
public class Singleton1 {
    private static Singleton1 instance;
    
    private Singleton1() {}
    
    public static Singleton1 getInstance() {
        if (instance == null) {
            instance = new Singleton1();  // 多线程问题
        }
        return instance;
    }
}

// ✅ 饿汉式(线程安全,推荐)
public class Singleton2 {
    private static final Singleton2 INSTANCE = new Singleton2();
    
    private Singleton2() {}
    
    public static Singleton2 getInstance() {
        return INSTANCE;
    }
}

// ✅ 双重检查锁(DCL,推荐)
public class Singleton3 {
    private static volatile Singleton3 instance;
    
    private Singleton3() {}
    
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized (Singleton3.class) {
                if (instance == null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
}

// ✅ 静态内部类(推荐)
public class Singleton4 {
    private Singleton4() {}
    
    private static class Holder {
        private static final Singleton4 INSTANCE = new Singleton4();
    }
    
    public static Singleton4 getInstance() {
        return Holder.INSTANCE;
    }
}

// ✅ 枚举(最安全,推荐)
public enum Singleton5 {
    INSTANCE;
    
    public void doSomething() {
        System.out.println("单例方法");
    }
}

应用场景:

  • 数据库连接池
  • 配置管理器
  • 日志对象
  • 线程池

2.2 工厂模式(Factory)

关键点: 定义创建对象的接口,让子类决定实例化哪个类。

java 复制代码
// 产品接口
public interface Product {
    void use();
}

// 具体产品
public class ConcreteProductA implements Product {
    @Override
    public void use() {
        System.out.println("使用产品A");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void use() {
        System.out.println("使用产品B");
    }
}

// ❌ 不使用工厂模式
public class Client1 {
    public static void main(String[] args) {
        Product product = new ConcreteProductA();  // 直接依赖具体类
        product.use();
    }
}

// ✅ 简单工厂模式
public class SimpleFactory {
    public static Product createProduct(String type) {
        switch (type) {
            case "A":
                return new ConcreteProductA();
            case "B":
                return new ConcreteProductB();
            default:
                throw new IllegalArgumentException("未知产品类型");
        }
    }
}

// 使用
public class Client2 {
    public static void main(String[] args) {
        Product product = SimpleFactory.createProduct("A");
        product.use();
    }
}

// ✅ 工厂方法模式
public interface Factory {
    Product createProduct();
}

public class FactoryA implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class FactoryB implements Factory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

// 使用
public class Client3 {
    public static void main(String[] args) {
        Factory factory = new FactoryA();
        Product product = factory.createProduct();
        product.use();
    }
}

应用场景:

  • JDBC连接
  • Spring的BeanFactory
  • 日志框架(SLF4J)

2.3 建造者模式(Builder)

关键点: 将复杂对象的构建与表示分离,使同样的构建过程可以创建不同的表示。

java 复制代码
// ❌ 传统构造方法(参数过多)
public class Computer1 {
    private String cpu;
    private String ram;
    private String disk;
    private String gpu;
    private String monitor;
    
    public Computer1(String cpu, String ram, String disk, 
                    String gpu, String monitor) {
        this.cpu = cpu;
        this.ram = ram;
        this.disk = disk;
        this.gpu = gpu;
        this.monitor = monitor;
    }
}

// 使用:参数顺序容易搞错
Computer1 computer = new Computer1("i7", "16G", "512G", "RTX3060", "27寸");

// ✅ 建造者模式
public class Computer {
    private String cpu;
    private String ram;
    private String disk;
    private String gpu;
    private String monitor;
    
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.disk = builder.disk;
        this.gpu = builder.gpu;
        this.monitor = builder.monitor;
    }
    
    public static class Builder {
        private String cpu;
        private String ram;
        private String disk;
        private String gpu;
        private String monitor;
        
        public Builder cpu(String cpu) {
            this.cpu = cpu;
            return this;
        }
        
        public Builder ram(String ram) {
            this.ram = ram;
            return this;
        }
        
        public Builder disk(String disk) {
            this.disk = disk;
            return this;
        }
        
        public Builder gpu(String gpu) {
            this.gpu = gpu;
            return this;
        }
        
        public Builder monitor(String monitor) {
            this.monitor = monitor;
            return this;
        }
        
        public Computer build() {
            return new Computer(this);
        }
    }
    
    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", ram='" + ram + '\'' +
                ", disk='" + disk + '\'' +
                ", gpu='" + gpu + '\'' +
                ", monitor='" + monitor + '\'' +
                '}';
    }
}

// 使用:链式调用,清晰易读
Computer computer = new Computer.Builder()
        .cpu("i7")
        .ram("16G")
        .disk("512G")
        .gpu("RTX3060")
        .monitor("27寸")
        .build();

应用场景:

  • StringBuilder
  • Lombok的@Builder
  • OkHttp的Request构建

三、结构型模式

3.1 代理模式(Proxy)

关键点: 为其他对象提供一种代理以控制对这个对象的访问。

java 复制代码
// 接口
public interface UserService {
    void save(String user);
    String query(String id);
}

// 真实对象
public class UserServiceImpl implements UserService {
    @Override
    public void save(String user) {
        System.out.println("保存用户:" + user);
    }
    
    @Override
    public String query(String id) {
        System.out.println("查询用户:" + id);
        return "User-" + id;
    }
}

// ✅ 静态代理
public class UserServiceProxy implements UserService {
    private UserService target;
    
    public UserServiceProxy(UserService target) {
        this.target = target;
    }
    
    @Override
    public void save(String user) {
        System.out.println("开始事务");
        target.save(user);
        System.out.println("提交事务");
    }
    
    @Override
    public String query(String id) {
        System.out.println("权限检查");
        String result = target.query(id);
        System.out.println("日志记录");
        return result;
    }
}

// ✅ 动态代理(JDK)
public class JdkProxyFactory {
    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            (proxy, method, args) -> {
                System.out.println("方法执行前:" + method.getName());
                Object result = method.invoke(target, args);
                System.out.println("方法执行后");
                return result;
            }
        );
    }
}

// 使用
public class ProxyDemo {
    public static void main(String[] args) {
        // 静态代理
        UserService proxy1 = new UserServiceProxy(new UserServiceImpl());
        proxy1.save("张三");
        
        // 动态代理
        UserService proxy2 = JdkProxyFactory.createProxy(new UserServiceImpl());
        proxy2.query("123");
    }
}

应用场景:

  • Spring AOP
  • MyBatis的Mapper接口
  • RPC远程调用

3.2 装饰器模式(Decorator)

关键点: 动态地给对象添加额外的职责,比继承更灵活。

java 复制代码
// 组件接口
public interface Coffee {
    double cost();
    String description();
}

// 具体组件
public class SimpleCoffee implements Coffee {
    @Override
    public double cost() {
        return 10.0;
    }
    
    @Override
    public String description() {
        return "普通咖啡";
    }
}

// 装饰器基类
public abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;
    
    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }
}

// 具体装饰器:加奶
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return coffee.cost() + 2.0;
    }
    
    @Override
    public String description() {
        return coffee.description() + " + 牛奶";
    }
}

// 具体装饰器:加糖
public class SugarDecorator extends CoffeeDecorator {
    public SugarDecorator(Coffee coffee) {
        super(coffee);
    }
    
    @Override
    public double cost() {
        return coffee.cost() + 1.0;
    }
    
    @Override
    public String description() {
        return coffee.description() + " + 糖";
    }
}

// 使用
public class DecoratorDemo {
    public static void main(String[] args) {
        // 普通咖啡
        Coffee coffee1 = new SimpleCoffee();
        System.out.println(coffee1.description() + " = " + coffee1.cost());
        
        // 加奶咖啡
        Coffee coffee2 = new MilkDecorator(new SimpleCoffee());
        System.out.println(coffee2.description() + " = " + coffee2.cost());
        
        // 加奶加糖咖啡
        Coffee coffee3 = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
        System.out.println(coffee3.description() + " = " + coffee3.cost());
    }
}

应用场景:

  • Java I/O流(BufferedReader、InputStreamReader)
  • Spring的BeanWrapper
  • MyBatis的Cache

四、行为型模式

4.1 策略模式(Strategy)

关键点: 定义一系列算法,把它们封装起来,并且使它们可以互相替换。

java 复制代码
// ❌ 不使用策略模式
public class PaymentService1 {
    public void pay(String type, double amount) {
        if ("alipay".equals(type)) {
            System.out.println("支付宝支付:" + amount);
        } else if ("wechat".equals(type)) {
            System.out.println("微信支付:" + amount);
        } else if ("bank".equals(type)) {
            System.out.println("银行卡支付:" + amount);
        }
        // 新增支付方式需要修改代码,违反开闭原则
    }
}

// ✅ 策略模式
// 策略接口
public interface PaymentStrategy {
    void pay(double amount);
}

// 具体策略
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("支付宝支付:" + amount);
    }
}

public class WechatStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("微信支付:" + amount);
    }
}

public class BankCardStrategy implements PaymentStrategy {
    @Override
    public void pay(double amount) {
        System.out.println("银行卡支付:" + amount);
    }
}

// 上下文
public class PaymentContext {
    private PaymentStrategy strategy;
    
    public void setStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public void pay(double amount) {
        strategy.pay(amount);
    }
}

// 使用
public class StrategyDemo {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();
        
        // 使用支付宝
        context.setStrategy(new AlipayStrategy());
        context.pay(100);
        
        // 切换为微信支付
        context.setStrategy(new WechatStrategy());
        context.pay(200);
    }
}

应用场景:

  • 支付方式选择
  • 排序算法选择
  • 文件压缩算法

4.2 观察者模式(Observer)

关键点: 定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。

java 复制代码
// 观察者接口
public interface Observer {
    void update(String message);
}

// 具体观察者
public class EmailObserver implements Observer {
    private String email;
    
    public EmailObserver(String email) {
        this.email = email;
    }
    
    @Override
    public void update(String message) {
        System.out.println("发送邮件到 " + email + ": " + message);
    }
}

public class SmsObserver implements Observer {
    private String phone;
    
    public SmsObserver(String phone) {
        this.phone = phone;
    }
    
    @Override
    public void update(String message) {
        System.out.println("发送短信到 " + phone + ": " + message);
    }
}

// 主题(被观察者)
public class Subject {
    private List<Observer> observers = new ArrayList<>();
    
    public void attach(Observer observer) {
        observers.add(observer);
    }
    
    public void detach(Observer observer) {
        observers.remove(observer);
    }
    
    public void notifyObservers(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

// 使用
public class ObserverDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();
        
        // 注册观察者
        subject.attach(new EmailObserver("user@example.com"));
        subject.attach(new SmsObserver("13800138000"));
        
        // 通知所有观察者
        subject.notifyObservers("订单已发货");
    }
}

应用场景:

  • 事件监听机制
  • MVC模式中的Model-View关系
  • 消息队列

4.3 模板方法模式(Template Method)

关键点: 定义算法骨架,将某些步骤延迟到子类实现。

java 复制代码
// 抽象类
public abstract class DataProcessor {
    
    // 模板方法(final防止子类重写)
    public final void process() {
        readData();
        processData();
        writeData();
    }
    
    // 具体方法
    private void readData() {
        System.out.println("读取数据");
    }
    
    // 抽象方法(子类必须实现)
    protected abstract void processData();
    
    // 钩子方法(子类可选择性重写)
    protected void writeData() {
        System.out.println("写入数据");
    }
}

// 具体类
public class CsvDataProcessor extends DataProcessor {
    @Override
    protected void processData() {
        System.out.println("处理CSV数据");
    }
}

public class JsonDataProcessor extends DataProcessor {
    @Override
    protected void processData() {
        System.out.println("处理JSON数据");
    }
    
    @Override
    protected void writeData() {
        System.out.println("写入JSON文件");
    }
}

// 使用
public class TemplateDemo {
    public static void main(String[] args) {
        DataProcessor csv = new CsvDataProcessor();
        csv.process();
        
        System.out.println("---");
        
        DataProcessor json = new JsonDataProcessor();
        json.process();
    }
}

应用场景:

  • Spring的JdbcTemplate
  • Servlet的service方法
  • 测试框架的setUp/tearDown

五、实战案例:电商订单系统

java 复制代码
// 1. 单例模式:配置管理器
public class ConfigManager {
    private static volatile ConfigManager instance;
    private Properties properties;
    
    private ConfigManager() {
        properties = new Properties();
        // 加载配置文件
    }
    
    public static ConfigManager getInstance() {
        if (instance == null) {
            synchronized (ConfigManager.class) {
                if (instance == null) {
                    instance = new ConfigManager();
                }
            }
        }
        return instance;
    }
    
    public String getProperty(String key) {
        return properties.getProperty(key);
    }
}

// 2. 工厂模式:订单创建
public interface Order {
    void create();
    void pay();
}

public class NormalOrder implements Order {
    @Override
    public void create() {
        System.out.println("创建普通订单");
    }
    
    @Override
    public void pay() {
        System.out.println("普通订单支付");
    }
}

public class GroupOrder implements Order {
    @Override
    public void create() {
        System.out.println("创建团购订单");
    }
    
    @Override
    public void pay() {
        System.out.println("团购订单支付");
    }
}

public class OrderFactory {
    public static Order createOrder(String type) {
        switch (type) {
            case "normal":
                return new NormalOrder();
            case "group":
                return new GroupOrder();
            default:
                throw new IllegalArgumentException("未知订单类型");
        }
    }
}

// 3. 策略模式:优惠计算
public interface DiscountStrategy {
    double calculate(double amount);
}

public class NoDiscountStrategy implements DiscountStrategy {
    @Override
    public double calculate(double amount) {
        return amount;
    }
}

public class PercentDiscountStrategy implements DiscountStrategy {
    private double percent;
    
    public PercentDiscountStrategy(double percent) {
        this.percent = percent;
    }
    
    @Override
    public double calculate(double amount) {
        return amount * percent;
    }
}

public class FullReductionStrategy implements DiscountStrategy {
    private double full;
    private double reduction;
    
    public FullReductionStrategy(double full, double reduction) {
        this.full = full;
        this.reduction = reduction;
    }
    
    @Override
    public double calculate(double amount) {
        return amount >= full ? amount - reduction : amount;
    }
}

// 4. 观察者模式:订单状态通知
public interface OrderObserver {
    void onOrderStatusChanged(String orderId, String status);
}

public class EmailNotifier implements OrderObserver {
    @Override
    public void onOrderStatusChanged(String orderId, String status) {
        System.out.println("邮件通知:订单" + orderId + "状态变更为" + status);
    }
}

public class SmsNotifier implements OrderObserver {
    @Override
    public void onOrderStatusChanged(String orderId, String status) {
        System.out.println("短信通知:订单" + orderId + "状态变更为" + status);
    }
}

public class OrderSubject {
    private List<OrderObserver> observers = new ArrayList<>();
    
    public void addObserver(OrderObserver observer) {
        observers.add(observer);
    }
    
    public void changeStatus(String orderId, String status) {
        System.out.println("订单" + orderId + "状态变更为:" + status);
        notifyObservers(orderId, status);
    }
    
    private void notifyObservers(String orderId, String status) {
        for (OrderObserver observer : observers) {
            observer.onOrderStatusChanged(orderId, status);
        }
    }
}

// 5. 建造者模式:订单构建
public class OrderInfo {
    private String orderId;
    private String userId;
    private List<String> products;
    private double amount;
    private String address;
    private String remark;
    
    private OrderInfo(Builder builder) {
        this.orderId = builder.orderId;
        this.userId = builder.userId;
        this.products = builder.products;
        this.amount = builder.amount;
        this.address = builder.address;
        this.remark = builder.remark;
    }
    
    public static class Builder {
        private String orderId;
        private String userId;
        private List<String> products = new ArrayList<>();
        private double amount;
        private String address;
        private String remark;
        
        public Builder orderId(String orderId) {
            this.orderId = orderId;
            return this;
        }
        
        public Builder userId(String userId) {
            this.userId = userId;
            return this;
        }
        
        public Builder addProduct(String product) {
            this.products.add(product);
            return this;
        }
        
        public Builder amount(double amount) {
            this.amount = amount;
            return this;
        }
        
        public Builder address(String address) {
            this.address = address;
            return this;
        }
        
        public Builder remark(String remark) {
            this.remark = remark;
            return this;
        }
        
        public OrderInfo build() {
            return new OrderInfo(this);
        }
    }
    
    @Override
    public String toString() {
        return "OrderInfo{" +
                "orderId='" + orderId + '\'' +
                ", userId='" + userId + '\'' +
                ", products=" + products +
                ", amount=" + amount +
                ", address='" + address + '\'' +
                ", remark='" + remark + '\'' +
                '}';
    }
}

// 综合使用
public class ECommerceDemo {
    public static void main(String[] args) {
        // 1. 创建订单
        Order order = OrderFactory.createOrder("normal");
        order.create();
        
        // 2. 构建订单信息
        OrderInfo orderInfo = new OrderInfo.Builder()
                .orderId("ORDER001")
                .userId("USER001")
                .addProduct("商品A")
                .addProduct("商品B")
                .amount(299.0)
                .address("北京市朝阳区")
                .remark("尽快发货")
                .build();
        
        System.out.println(orderInfo);
        
        // 3. 计算优惠
        DiscountStrategy strategy = new FullReductionStrategy(200, 30);
        double finalAmount = strategy.calculate(orderInfo.amount);
        System.out.println("优惠后金额:" + finalAmount);
        
        // 4. 订单状态通知
        OrderSubject subject = new OrderSubject();
        subject.addObserver(new EmailNotifier());
        subject.addObserver(new SmsNotifier());
        
        subject.changeStatus("ORDER001", "已支付");
        subject.changeStatus("ORDER001", "已发货");
    }
}

六、设计模式对比

6.1 工厂模式 vs 建造者模式

特性 工厂模式 建造者模式
目的 创建对象 构建复杂对象
关注点 创建什么 如何创建
参数 简单参数 复杂参数
使用场景 创建简单对象 创建复杂对象

6.2 代理模式 vs 装饰器模式

特性 代理模式 装饰器模式
目的 控制访问 增强功能
关注点 访问控制 功能扩展
对象关系 代理持有真实对象 装饰器包装组件
使用场景 权限控制、延迟加载 动态添加功能

6.3 策略模式 vs 状态模式

特性 策略模式 状态模式
目的 算法替换 状态转换
关注点 行为选择 状态变化
切换方式 客户端切换 自动切换
使用场景 多种算法选择 对象状态变化

七、常见面试题

7.1 单例模式的几种实现方式?

  1. 饿汉式:类加载时创建,线程安全
  2. 懒汉式:使用时创建,需要同步
  3. 双重检查锁:延迟加载+线程安全
  4. 静态内部类:延迟加载+线程安全
  5. 枚举:最安全,防止反射和序列化破坏

7.2 Spring中使用了哪些设计模式?

  • 单例模式:Bean默认单例
  • 工厂模式:BeanFactory
  • 代理模式:AOP
  • 模板方法:JdbcTemplate
  • 观察者模式:事件监听
  • 适配器模式:HandlerAdapter
  • 装饰器模式:BeanWrapper

7.3 如何选择合适的设计模式?

  1. 分析问题本质
  2. 考虑扩展性和维护性
  3. 遵循设计原则
  4. 不要过度设计
  5. 结合实际场景

八、总结

设计模式的核心要点:

  1. 创建型 - 如何创建对象
  2. 结构型 - 如何组合对象
  3. 行为型 - 对象间如何协作

最佳实践:

  • 理解设计原则,灵活运用模式
  • 不要为了用模式而用模式
  • 结合实际业务场景选择
  • 保持代码简洁,避免过度设计

学习建议:

  • 先理解原理,再看源码
  • 多写代码,多实践
  • 阅读优秀框架源码
  • 总结归纳,形成自己的理解

相关资源


💡 小贴士: 设计模式不是银弹,要根据实际情况灵活运用!

关注我,获取更多Java干货!

相关推荐
horizon72741 小时前
【Redis】Redis 分片集群搭建与故障转移实战指南
java·redis
小白勇闯网安圈2 小时前
Java的集合
java·开发语言
Revol_C2 小时前
开箱即用!轻量级轮询方案,支持同步获取轮询结果!
前端·javascript·设计模式
大学生资源网2 小时前
基于springboot的乡村信息化管理系统的研究与实现(源码+文档)
java·spring boot·后端
鹿角片ljp2 小时前
力扣 83: 删除排序链表中的重复元素(Java实现)
java·leetcode·链表
渣渣盟2 小时前
网络命令大全:轻松解决网络故障
开发语言·php
Mr Tang2 小时前
Docker日志查看和应用日志查看命令大全
java·开发语言
invicinble2 小时前
java处理数据合集
java·开发语言
电商API_180079052472 小时前
淘宝评论API技术解析与调用实战指南
开发语言·爬虫·信息可视化