Java 中的设计模式:经典与现代实践

Java 中的设计模式:经典与现代实践

1. 设计模式简介

设计模式是一种软件开发中的思想,它为我们提供了一些经过验证的、能够应对常见问题的解决方案。学习和掌握设计模式能够让开发者在面对复杂的需求时,能够设计出更加灵活、可维护的代码。现代 Java 语言的特点(如 Lambda 表达式Stream APIOptional)使得设计模式的实现更加简洁和高效。

设计模式按照其功能可以分为三大类:

  1. 创建型模式:用于对象创建,避免直接实例化。
  2. 结构型模式:用于类和对象的组合,解决系统中类之间的关系问题。
  3. 行为型模式:描述对象之间的交互和职责划分。

在这篇文章中,我们将通过现代 Java 的特性来重构经典设计模式的实现,帮助开发者更好地理解和运用设计模式。


2. 创建型设计模式

2.1 工厂模式(Factory Pattern)

经典实现

工厂模式通过封装对象的创建逻辑,将客户端与具体类的实例化解耦。通常适用于在创建对象时需要复杂逻辑或者希望通过参数控制生成不同对象的场景。

经典代码示例
java 复制代码
// 产品接口
public interface Car {
    void drive();
}

// 具体产品类
public class BMW implements Car {
    @Override
    public void drive() {
        System.out.println("Driving BMW...");
    }
}

public class Audi implements Car {
    @Override
    public void drive() {
        System.out.println("Driving Audi...");
    }
}

// 工厂类
public class CarFactory {
    public static Car createCar(String type) {
        switch (type.toLowerCase()) {
            case "bmw": return new BMW();
            case "audi": return new Audi();
            default: throw new IllegalArgumentException("Unknown car type");
        }
    }
}
现代 Java 实现:使用 Lambda 表达式

我们可以使用 Lambda 表达式 来简化工厂模式的实现,减少冗长的 if-elseswitch 语句,使得代码更简洁、灵活。

java 复制代码
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class CarFactory {
    private static final Map<String, Supplier<Car>> carRegistry = new HashMap<>();

    static {
        carRegistry.put("bmw", BMW::new);
        carRegistry.put("audi", Audi::new);
    }

    public static Car createCar(String type) {
        Supplier<Car> carSupplier = carRegistry.get(type.toLowerCase());
        if (carSupplier == null) {
            throw new IllegalArgumentException("Unknown car type");
        }
        return carSupplier.get();
    }
}
Spring 框架中的工厂模式

在 Spring 框架中,ApplicationContext 就是工厂模式的实现,它负责实例化并管理 Bean。

java 复制代码
// Spring 通过工厂模式实例化 Bean
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = context.getBean("car", Car.class);
car.drive();

3. 结构型设计模式

3.1 代理模式(Proxy Pattern)

经典实现

代理模式通过引入代理对象来控制对真实对象的访问。代理对象可以在调用目标对象之前或之后增加额外的逻辑,比如日志、权限控制等。

经典代码示例
java 复制代码
// 服务接口
public interface UserService {
    void createUser(String username);
}

// 真实服务类
public class RealUserService implements UserService {
    @Override
    public void createUser(String username) {
        System.out.println("Creating user: " + username);
    }
}

// 代理类
public class UserServiceProxy implements UserService {
    private final RealUserService realUserService = new RealUserService();

    @Override
    public void createUser(String username) {
        System.out.println("Logging: Start creating user");
        realUserService.createUser(username);
        System.out.println("Logging: End creating user");
    }
}
现代 Java 实现:使用 Java 8 的 StreamOptional

我们可以利用 Java 8 的 Optional 来避免 null 值的处理,并使用 Stream API 来简化数据的处理。

java 复制代码
public class UserServiceProxy implements UserService {
    private final RealUserService realUserService = new RealUserService();

    @Override
    public void createUser(String username) {
        Optional.of(username)
                .filter(name -> !name.isEmpty())
                .ifPresentOrElse(
                        name -> {
                            System.out.println("Logging: Start creating user");
                            realUserService.createUser(name);
                            System.out.println("Logging: End creating user");
                        },
                        () -> System.out.println("Invalid username")
                );
    }
}
Spring AOP 中的代理模式

Spring 的 AOP(面向切面编程)就是利用代理模式来增强目标方法的功能。Spring 使用 JDK 动态代理CGLIB 代理 来生成代理对象。

java 复制代码
@Service
public class OrderService {
    @Transactional
    public void createOrder() {
        // 事务管理由代理类处理
    }
}

4. 行为型设计模式

4.1 策略模式(Strategy Pattern)

经典实现

策略模式通过定义一系列算法并将每个算法封装到独立的策略类中,使得算法的选择和使用变得灵活。策略模式能够在运行时动态地改变策略。

经典代码示例
java 复制代码
public interface PaymentStrategy {
    void pay(int amount);
}

public class CreditCardPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using Credit Card");
    }
}

public class PayPalPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using PayPal");
    }
}

public class PaymentContext {
    private PaymentStrategy strategy;

    public void setPaymentStrategy(PaymentStrategy strategy) {
        this.strategy = strategy;
    }

    public void executePayment(int amount) {
        strategy.pay(amount);
    }
}
现代 Java 实现:使用 Stream 进行策略选择

可以通过 Stream API 来简化策略的选择过程,让代码更加简洁和优雅。

java 复制代码
public class PaymentContext {
    private Map<String, PaymentStrategy> strategies = Map.of(
        "credit", new CreditCardPayment(),
        "paypal", new PayPalPayment()
    );

    public void executePayment(String paymentType, int amount) {
        Optional.ofNullable(strategies.get(paymentType))
                .ifPresentOrElse(
                        strategy -> strategy.pay(amount),
                        () -> System.out.println("Invalid payment method")
                );
    }
}
Spring 中的策略模式

Spring 中的 HandlerMapping 就是使用策略模式的一个例子,它通过不同的请求类型和处理器选择不同的处理策略。

java 复制代码
public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}

不同类型的 HandlerAdapter 处理不同的 Controller,如 SimpleControllerHandlerAdapter 处理 SimpleController


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

经典实现

模板方法模式通过定义一个算法的骨架,将某些步骤的实现延迟到子类中。这样,子类可以在保留算法结构的同时定制部分实现。

经典代码示例
java 复制代码
public abstract class DataProcessor {
    public void process() {
        readData();
        processData();
        writeData();
    }

    protected abstract void readData();
    protected abstract void processData();
    protected abstract void writeData();
}

public class CSVDataProcessor extends DataProcessor {
    @Override
    protected void readData() {
        System.out.println("Reading CSV data...");
    }

    @Override
    protected void processData() {
        System.out.println("Processing CSV data...");
    }

    @Override
    protected void writeData() {
        System.out.println("Writing CSV data...");
    }
}
现代 Java 实现:使用 Lambda 表达式和 Optional

我们可以结合 Lambda 表达式 来动态传入处理步骤,让模板方法的使用更加灵活。

java 复制代码
public abstract class DataProcessor {
    public void process() {
        processStep(this::readData, "Reading");
        processStep(this::processData, "Processing");
        processStep(this::writeData, "Writing");
    }

    private void processStep(Runnable step, String stepName) {
        System.out.println(stepName + " data...");
        step.run();
    }

    protected abstract void readData();
    protected abstract void processData();
    protected abstract void writeData();
}

6. 总结

通过结合现代 Java 特性,我们可以让经典的设计模式变得更加简洁和高效。 Lambda 表达式Stream API 为我们的设计模式实现提供了更灵活的方式,而 Optional 可以帮助我们避免空指针异常,使得代码更加健壮。

在实际的项目开发中,理解和运用设计模式能够大大提高代码的可维护性和可扩展性。希望本文的示例能够帮助你更好地理解设计模式,并在实际开发中灵活运用。

相关推荐
gentle_ice2 分钟前
leetcode——矩阵置零(java)
java·算法·leetcode·矩阵
stevewongbuaa29 分钟前
一些烦人的go设置 goland
开发语言·后端·golang
撸码到无法自拔1 小时前
MATLAB中处理大数据的技巧与方法
大数据·开发语言·matlab
whisperrr.1 小时前
【JavaWeb06】Tomcat基础入门:架构理解与基本配置指南
java·架构·tomcat
island13141 小时前
【QT】 控件 -- 显示类
开发语言·数据库·qt
sysu631 小时前
95.不同的二叉搜索树Ⅱ python
开发语言·数据结构·python·算法·leetcode·面试·深度优先
hust_joker2 小时前
go单元测试和基准测试
开发语言·golang·单元测试
火烧屁屁啦2 小时前
【JavaEE进阶】应用分层
java·前端·java-ee
m0_748257462 小时前
鸿蒙NEXT(五):鸿蒙版React Native架构浅析
java
我没想到原来他们都是一堆坏人2 小时前
2023年版本IDEA复制项目并修改端口号和运行内存
java·ide·intellij-idea