Java 中的设计模式:经典与现代实践
1. 设计模式简介
设计模式是一种软件开发中的思想,它为我们提供了一些经过验证的、能够应对常见问题的解决方案。学习和掌握设计模式能够让开发者在面对复杂的需求时,能够设计出更加灵活、可维护的代码。现代 Java 语言的特点(如 Lambda 表达式、Stream API、Optional)使得设计模式的实现更加简洁和高效。
设计模式按照其功能可以分为三大类:
- 创建型模式:用于对象创建,避免直接实例化。
- 结构型模式:用于类和对象的组合,解决系统中类之间的关系问题。
- 行为型模式:描述对象之间的交互和职责划分。
在这篇文章中,我们将通过现代 Java 的特性来重构经典设计模式的实现,帮助开发者更好地理解和运用设计模式。
2. 创建型设计模式
2.1 工厂模式(Factory Pattern)
经典实现
工厂模式通过封装对象的创建逻辑,将客户端与具体类的实例化解耦。通常适用于在创建对象时需要复杂逻辑或者希望通过参数控制生成不同对象的场景。
经典代码示例
// 产品接口
public interface Car {void drive();
}// 具体产品类
public class BMW implements Car {@Overridepublic void drive() {System.out.println("Driving BMW...");}
}public class Audi implements Car {@Overridepublic 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-else
或 switch
语句,使得代码更简洁、灵活。
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。
// Spring 通过工厂模式实例化 Bean
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Car car = context.getBean("car", Car.class);
car.drive();
3. 结构型设计模式
3.1 代理模式(Proxy Pattern)
经典实现
代理模式通过引入代理对象来控制对真实对象的访问。代理对象可以在调用目标对象之前或之后增加额外的逻辑,比如日志、权限控制等。
经典代码示例
// 服务接口
public interface UserService {void createUser(String username);
}// 真实服务类
public class RealUserService implements UserService {@Overridepublic void createUser(String username) {System.out.println("Creating user: " + username);}
}// 代理类
public class UserServiceProxy implements UserService {private final RealUserService realUserService = new RealUserService();@Overridepublic void createUser(String username) {System.out.println("Logging: Start creating user");realUserService.createUser(username);System.out.println("Logging: End creating user");}
}
现代 Java 实现:使用 Java 8 的 Stream
和 Optional
我们可以利用 Java 8 的 Optional 来避免 null
值的处理,并使用 Stream API 来简化数据的处理。
public class UserServiceProxy implements UserService {private final RealUserService realUserService = new RealUserService();@Overridepublic 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 代理 来生成代理对象。
@Service
public class OrderService {@Transactionalpublic void createOrder() {// 事务管理由代理类处理}
}
4. 行为型设计模式
4.1 策略模式(Strategy Pattern)
经典实现
策略模式通过定义一系列算法并将每个算法封装到独立的策略类中,使得算法的选择和使用变得灵活。策略模式能够在运行时动态地改变策略。
经典代码示例
public interface PaymentStrategy {void pay(int amount);
}public class CreditCardPayment implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("Paying " + amount + " using Credit Card");}
}public class PayPalPayment implements PaymentStrategy {@Overridepublic 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 来简化策略的选择过程,让代码更加简洁和优雅。
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
就是使用策略模式的一个例子,它通过不同的请求类型和处理器选择不同的处理策略。
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)
经典实现
模板方法模式通过定义一个算法的骨架,将某些步骤的实现延迟到子类中。这样,子类可以在保留算法结构的同时定制部分实现。
经典代码示例
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 {@Overrideprotected void readData() {System.out.println("Reading CSV data...");}@Overrideprotected void processData() {System.out.println("Processing CSV data...");}@Overrideprotected void writeData() {System.out.println("Writing CSV data...");}
}
现代 Java 实现:使用 Lambda 表达式和 Optional
我们可以结合 Lambda 表达式 来动态传入处理步骤,让模板方法的使用更加灵活。
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 可以帮助我们避免空指针异常,使得代码更加健壮。
在实际的项目开发中,理解和运用设计模式能够大大提高代码的可维护性和可扩展性。希望本文的示例能够帮助你更好地理解设计模式,并在实际开发中灵活运用。