设计模式
1、装饰器模式
/**
核心: 通过组合而非继承,在不修改原接口的情况下,动态扩展功能。解决了“类膨胀”的问题。
组件:
Component(组件接口):定义对象的基本接口
ConcreteComponent(具体组件):实现基本接口的原始对象 (自己干活)
Decorator(装饰器抽象类):持有Component引用,并实现相同接口 (转交给别人干活)
ConcreteDecorator(具体装饰器):扩展Decorator,添加具体功能 (转交给别人干活,同时自己也干点活)
原理:装饰器对象包装原始对象,形成装饰器链。每个装饰器都可以在调用原始方法前后添加自己的逻辑,然后将调用传递给下一个对象。
优势:
开闭原则:对扩展开放,对修改关闭
灵活性:可以任意组合多个装饰器
职责分离:每个装饰器只负责一个特定功能
运行时扩展:可以在运行时动态添加或移除功能
应用场景:
输入输出流处理(如Java的BufferedReader包装FileReader)
中间件系统(如Express.js中间件)
权限验证、日志记录、缓存等横切关注点(Spring AOP)
Servlet Filter请求过滤器链
**/
咖啡订单系统
/**
问题:需要支持各种配料组合(牛奶、糖、奶泡等)
解决:每种配料作为一个装饰器,可以任意组合
优势:避免创建大量子类(如MilkSugarCoffee、MilkCoffee等)
**/
// 场景:咖啡订单系统 - 动态添加配料
interface Coffee {
String getDescription();
double getCost();
}
class SimpleCoffee implements Coffee {
public String getDescription() {
return "Simple Coffee";
}
public double getCost() {
return 2.0;
}
}
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
public String getDescription() {
return coffee.getDescription();
}
public double getCost() {
return coffee.getCost();
}
}
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
public String getDescription() {
return coffee.getDescription() + ", Milk";
}
public double getCost() {
return coffee.getCost() + 0.5;
}
}
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
public String getDescription() {
return coffee.getDescription() + ", Sugar";
}
public double getCost() {
return coffee.getCost() + 0.2;
}
}
实际业务场景
数据连接池
查看代码
// 1. 基础连接接口
interface DatabaseConnection {
ResultSet executeQuery(String sql) throws SQLException;
int executeUpdate(String sql) throws SQLException;
void close() throws SQLException;
}
// 2. 真实数据库连接
class RealConnection implements DatabaseConnection {
private Connection conn;
private String id;
public RealConnection(String url, String user, String pwd) throws SQLException {
this.conn = DriverManager.getConnection(url, user, pwd);
this.id = "CONN-" + System.currentTimeMillis();
}
public ResultSet executeQuery(String sql) throws SQLException {
return conn.createStatement().executeQuery(sql);
}
public int executeUpdate(String sql) throws SQLException {
return conn.createStatement().executeUpdate(sql);
}
public void close() throws SQLException {
if (conn != null) conn.close();
}
public String getId() { return id; }
}
// 3. 装饰器基类
abstract class ConnectionDecorator implements DatabaseConnection {
protected DatabaseConnection connection;
public ConnectionDecorator(DatabaseConnection conn) {
this.connection = conn;
}
public ResultSet executeQuery(String sql) throws SQLException {
return connection.executeQuery(sql);
}
public int executeUpdate(String sql) throws SQLException {
return connection.executeUpdate(sql);
}
public void close() throws SQLException {
connection.close();
}
}
// 4. 连接池装饰器(核心)
class PooledConnection extends ConnectionDecorator {
private ConnectionPool pool;
private boolean inPool = false;
public PooledConnection(DatabaseConnection conn, ConnectionPool pool) {
super(conn);
this.pool = pool;
}
@Override
public void close() throws SQLException {
if (!inPool) {
inPool = true;
pool.returnConnection(this); // 返回池中,不真正关闭
}
}
public void realClose() throws SQLException {
super.close(); // 真正关闭连接
}
public void reset() {
inPool = false;
}
}
// 5. 监控装饰器
class MonitoringDecorator extends ConnectionDecorator {
private AtomicInteger queryCount = new AtomicInteger(0);
private AtomicLong totalTime = new AtomicLong(0);
public MonitoringDecorator(DatabaseConnection conn) {
super(conn);
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
long start = System.currentTimeMillis();
try {
return super.executeQuery(sql);
} finally {
queryCount.incrementAndGet();
totalTime.addAndGet(System.currentTimeMillis() - start);
}
}
public void printStats() {
System.out.println("查询次数: " + queryCount + ", 总耗时: " + totalTime + "ms");
}
}
// 6. 缓存装饰器
class CachedConnection extends ConnectionDecorator {
private Map<String, ResultSet> cache = new ConcurrentHashMap<>();
public CachedConnection(DatabaseConnection conn) {
super(conn);
}
@Override
public ResultSet executeQuery(String sql) throws SQLException {
if (cache.containsKey(sql)) {
System.out.println("缓存命中: " + sql);
return cache.get(sql);
}
ResultSet rs = super.executeQuery(sql);
cache.put(sql, rs);
return rs;
}
@Override
public int executeUpdate(String sql) throws SQLException {
cache.clear(); // 更新时清空缓存
return super.executeUpdate(sql);
}
}
// 7. 连接池实现
class ConnectionPool {
private final BlockingQueue<PooledConnection> available = new LinkedBlockingQueue<>();
private final Set<PooledConnection> used = ConcurrentHashMap.newKeySet();
private final String url, user, pwd;
private final int maxSize;
public ConnectionPool(String url, String user, String pwd, int maxSize) {
this.url = url; this.user = user; this.pwd = pwd; this.maxSize = maxSize;
// 预创建连接
for (int i = 0; i < maxSize / 2; i++) {
try {
available.offer(new PooledConnection(new RealConnection(url, user, pwd), this));
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public DatabaseConnection getConnection() throws SQLException {
PooledConnection conn = available.poll();
if (conn == null && used.size() < maxSize) {
conn = new PooledConnection(new RealConnection(url, user, pwd), this);
}
if (conn == null) {
throw new SQLException("连接池已满");
}
conn.reset();
used.add(conn);
return conn;
}
public void returnConnection(PooledConnection conn) {
if (used.remove(conn)) {
available.offer(conn);
}
}
public void shutdown() {
available.forEach(conn -> {
try { conn.realClose(); } catch (SQLException e) { e.printStackTrace(); }
});
used.forEach(conn -> {
try { conn.realClose(); } catch (SQLException e) { e.printStackTrace(); }
});
}
}
// 8. 连接工厂
class ConnectionFactory {
private ConnectionPool pool;
public ConnectionFactory(String url, String user, String pwd, int poolSize) {
this.pool = new ConnectionPool(url, user, pwd, poolSize);
}
public DatabaseConnection create(String type) throws SQLException {
DatabaseConnection conn = pool.getConnection();
switch (type) {
case "monitored":
return new MonitoringDecorator(conn);
case "cached":
return new CachedConnection(conn);
case "enterprise":
return new MonitoringDecorator(new CachedConnection(conn));
default:
return conn;
}
}
public void shutdown() { pool.shutdown(); }
}
// 9. 使用示例
public class ConnectionPoolExample {
public static void main(String[] args) throws SQLException {
ConnectionFactory factory = new ConnectionFactory("jdbc:h2:mem:test", "sa", "", 5);
// 普通连接
DatabaseConnection basic = factory.create("basic");
basic.close();
// 企业级连接(监控+缓存)
DatabaseConnection enterprise = factory.create("enterprise");
enterprise.close();
factory.shutdown();
}
}
Spring AOP
查看代码
// 1. 业务接口
interface UserService {
User getUserById(Long id);
void updateUser(User user);
void deleteUser(Long id);
}
// 2. 核心业务实现
@Service
public class UserServiceImpl implements UserService {
@Override
public User getUserById(Long id) {
// 模拟数据库查询
System.out.println("从数据库查询用户: " + id);
return new User(id, "User" + id, "user" + id + "@example.com");
}
@Override
public void updateUser(User user) {
System.out.println("更新用户: " + user.getName());
// 模拟更新操作
}
@Override
public void deleteUser(Long id) {
System.out.println("删除用户: " + id);
// 模拟删除操作
}
}
// 3. 用户实体
class User {
private Long id;
private String name;
private String email;
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// getters and setters
public Long getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
}
// 4. 性能监控装饰器 - 通过AOP实现
@Aspect
@Component
public class PerformanceMonitoringAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
String className = joinPoint.getTarget().getClass().getSimpleName();
long startTime = System.currentTimeMillis();
Object result = null;
try {
System.out.println("🔍 [性能监控] 开始执行: " + className + "." + methodName);
result = joinPoint.proceed();
return result;
} finally {
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("⏱️ [性能监控] " + className + "." + methodName + " 执行耗时: " + duration + "ms");
}
}
}
// 5. 缓存装饰器 - 通过AOP实现
@Aspect
@Component
public class CacheAspect {
private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
private final long CACHE_EXPIRE_TIME = 30000; // 30秒
@Around("execution(* com.example.service.*.get*(..))")
public Object cacheGet(ProceedingJoinPoint joinPoint) throws Throwable {
String cacheKey = generateCacheKey(joinPoint);
// 检查缓存
CacheEntry entry = cache.get(cacheKey);
if (entry != null && !entry.isExpired()) {
System.out.println("✅ [缓存命中] " + cacheKey);
return entry.getValue();
}
// 执行原方法
Object result = joinPoint.proceed();
// 存入缓存
cache.put(cacheKey, new CacheEntry(result, System.currentTimeMillis() + CACHE_EXPIRE_TIME));
System.out.println("💾 [缓存存储] " + cacheKey);
return result;
}
@After("execution(* com.example.service.*.update*(..) || execution(* com.example.service.*.delete*(..))")
public void clearCache() {
cache.clear();
System.out.println("🗑️ [缓存清理] 数据变更,清空缓存");
}
private String generateCacheKey(ProceedingJoinPoint joinPoint) {
StringBuilder key = new StringBuilder();
key.append(joinPoint.getTarget().getClass().getSimpleName())
.append(".")
.append(joinPoint.getSignature().getName());
Object[] args = joinPoint.getArgs();
if (args != null && args.length > 0) {
key.append("(");
for (int i = 0; i < args.length; i++) {
if (i > 0) key.append(",");
key.append(args[i]);
}
key.append(")");
}
return key.toString();
}
private static class CacheEntry {
private Object value;
private long expireTime;
public CacheEntry(Object value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}
public boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
public Object getValue() {
return value;
}
}
}
// 6. 日志装饰器
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("📝 [日志] 方法调用: " + methodName + ", 参数: " + Arrays.toString(args));
}
@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("✅ [日志] 方法成功: " + methodName + ", 返回值: " + result);
}
@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("❌ [日志] 方法异常: " + methodName + ", 异常: " + ex.getMessage());
}
}
// 7. 事务装饰器
@Aspect
@Component
public class TransactionAspect {
@Around("execution(* com.example.service.*.update*(..) || execution(* com.example.service.*.delete*(..))")
public Object handleTransaction(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
System.out.println("🔒 [事务] 开始事务: " + methodName);
try {
Object result = joinPoint.proceed();
System.out.println("✅ [事务] 提交事务: " + methodName);
return result;
} catch (Exception e) {
System.out.println("❌ [事务] 回滚事务: " + methodName + ", 原因: " + e.getMessage());
throw e;
}
}
}
// 8. 权限检查装饰器
@Aspect
@Component
public class SecurityAspect {
@Before("execution(* com.example.service.*.delete*(..))")
public void checkDeletePermission(JoinPoint joinPoint) {
// 模拟权限检查
String currentUser = getCurrentUser();
if (!"admin".equals(currentUser)) {
throw new SecurityException("用户 " + currentUser + " 无删除权限");
}
System.out.println("🔐 [权限] 删除权限检查通过");
}
@Before("execution(* com.example.service.*.update*(..))")
public void checkUpdatePermission(JoinPoint joinPoint) {
String currentUser = getCurrentUser();
Object[] args = joinPoint.getArgs();
if (args.length > 0 && args[0] instanceof User) {
User user = (User) args[0];
if (!currentUser.equals("admin") && !currentUser.equals(user.getName())) {
throw new SecurityException("用户 " + currentUser + " 无权限修改其他用户信息");
}
}
System.out.println("🔐 [权限] 更新权限检查通过");
}
private String getCurrentUser() {
// 模拟获取当前用户
return "admin"; // 实际应用中从SecurityContext获取
}
}
// 9. 重试装饰器
@Aspect
@Component
public class RetryAspect {
@Around("execution(* com.example.service.*.get*(..))")
public Object retry(ProceedingJoinPoint joinPoint) throws Throwable {
int maxRetries = 3;
int retryCount = 0;
while (retryCount < maxRetries) {
try {
return joinPoint.proceed();
} catch (Exception e) {
retryCount++;
if (retryCount >= maxRetries) {
System.out.println("🔄 [重试] 达到最大重试次数,失败");
throw e;
}
System.out.println("🔄 [重试] 第" + retryCount + "次重试...");
Thread.sleep(1000); // 等待1秒后重试
}
}
return null;
}
}
// 10. 配置类
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
@Bean
public PerformanceMonitoringAspect performanceMonitoringAspect() {
return new PerformanceMonitoringAspect();
}
@Bean
public CacheAspect cacheAspect() {
return new CacheAspect();
}
@Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect();
}
@Bean
public TransactionAspect transactionAspect() {
return new TransactionAspect();
}
@Bean
public SecurityAspect securityAspect() {
return new SecurityAspect();
}
@Bean
public RetryAspect retryAspect() {
return new RetryAspect();
}
}
// 11. 使用示例
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@PutMapping("/users")
public void updateUser(@RequestBody User user) {
userService.updateUser(user);
}
@DeleteMapping("/users/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
}
// 12. 测试类
@SpringBootTest
public class AopDecoratorTest {
@Autowired
private UserService userService;
@Test
public void testDecoratorChain() {
// 测试查询操作(应用:重试 + 缓存 + 性能监控 + 日志)
System.out.println("=== 测试查询操作 ===");
User user1 = userService.getUserById(1L);
User user2 = userService.getUserById(1L); // 第二次查询应该命中缓存
// 测试更新操作(应用:事务 + 权限 + 性能监控 + 日志 + 缓存清理)
System.out.println("\n=== 测试更新操作 ===");
userService.updateUser(new User(1L, "UpdatedUser", "updated@example.com"));
// 测试删除操作(应用:事务 + 权限 + 性能监控 + 日志 + 缓存清理)
System.out.println("\n=== 测试删除操作 ===");
userService.deleteUser(1L);
}
}
// 13. 主应用类
@SpringBootApplication
public class AopDecoratorApplication {
public static void main(String[] args) {
SpringApplication.run(AopDecoratorApplication.class, args);
}
}
Servlet过滤器链
查看代码
// 核心接口
public interface Filter {
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
}
// 过滤器链接口
public interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException;
}
// 装饰器实现:每个Filter都可以看作是对原始请求/响应的装饰器
public class LoggingFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 前置处理 - 装饰请求
System.out.println("请求开始: " + ((HttpServletRequest)request).getRequestURI());
// 调用链中的下一个过滤器或目标Servlet
chain.doFilter(request, response);
// 后置处理 - 装饰响应
System.out.println("请求结束");
}
}
// 链式装饰
public class AuthenticationFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 身份验证装饰
HttpServletRequest httpRequest = (HttpServletRequest) request;
String token = httpRequest.getHeader("Authorization");
if (isValidToken(token)) {
// 通过验证,继续链式调用
chain.doFilter(request, response);
} else {
// 验证失败,中断链
((HttpServletResponse) response).setStatus(401);
}
}
}
// 字符编码过滤器
public class CharacterEncodingFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
// 性能监控过滤器
public class PerformanceFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
long startTime = System.currentTimeMillis();
chain.doFilter(request, response);
long endTime = System.currentTimeMillis();
System.out.println("请求处理时间: " + (endTime - startTime) + "ms");
}
}
注意:实际开发中,还需要配置web.xml
查看代码
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>com.example.CharacterEncodingFilter</filter-class>
</filter>
<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>com.example.AuthenticationFilter</filter-class>
</filter>
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>com.example.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Java I/O流(BufferedReader装饰FileReader)

浙公网安备 33010602011771号