返回
从实际需求看代理模式和装饰器模式
前端
2023-12-28 05:13:43
问题引入
某天产品同学来找我。
产品同学🤵:有一个需求,需要对扩容操作加上权限判断。
加菲猫🐱:好的。
加菲猫🐱:改完了,看下。
相信很多同学都会这样写。
public class UserService {
public void expand(User user) {
// 权限判断
if (user.getPermission() != Permission.ADMIN) {
throw new RuntimeException("无权扩容");
}
// 业务逻辑
user.setCapacity(user.getCapacity() * 2);
}
}
在上面这个简单的场景中,这样确实可行。但是后来,产品同学又提出了一个需求。
产品同学🤵:扩容操作不仅要加上权限判断,还要加上日志记录。
加菲猫🐱:好的,我马上改。
改完后,产品同学又提出了一个需求。
产品同学🤵:扩容操作不仅要加上权限判断和日志记录,还要加上缓存。
加菲猫🐱:好的,我再改一下。
改完后,产品同学又提出了一个需求。
产品同学🤵:扩容操作不仅要加上权限判断、日志记录和缓存,还要加上限流。
加菲猫🐱:好的,我再再改一下。
就这样,加菲猫🐱改了又改,改了又改。
终于有一天,加菲猫🐱受不了了。
加菲猫🐱:产品同学,你能不能一次性把需求说清楚?
产品同学🤵:我这不是在给你锻炼代码重构的能力吗?
加菲猫🐱:……
代理模式
代理模式是一种设计模式,它允许一个对象代表另一个对象。这样,代理对象可以控制对另一个对象的访问。
代理模式有两种主要类型:
- 静态代理模式 :静态代理模式中,代理对象和被代理对象都实现相同的接口。这样,代理对象可以透明地替换被代理对象。
- 动态代理模式 :动态代理模式中,代理对象不需要实现相同的接口。这样,代理对象可以更灵活地控制对被代理对象的访问。
在我们的例子中,我们可以使用代理模式来实现对扩容操作的权限判断、日志记录、缓存和限流。
public class UserServiceProxy implements UserService {
private UserService userService;
public UserServiceProxy(UserService userService) {
this.userService = userService;
}
@Override
public void expand(User user) {
// 权限判断
if (user.getPermission() != Permission.ADMIN) {
throw new RuntimeException("无权扩容");
}
// 日志记录
log.info("扩容操作:{}", user.getUsername());
// 缓存
cache.put(user.getId(), user);
// 限流
limiter.acquire();
// 业务逻辑
userService.expand(user);
}
}
装饰器模式
装饰器模式是一种设计模式,它允许在不改变原有对象的基础上,为其添加新的功能。
装饰器模式有两种主要类型:
- 静态装饰器模式 :静态装饰器模式中,装饰器对象和被装饰对象都实现相同的接口。这样,装饰器对象可以透明地替换被装饰对象。
- 动态装饰器模式 :动态装饰器模式中,装饰器对象不需要实现相同的接口。这样,装饰器对象可以更灵活地控制对被装饰对象的访问。
在我们的例子中,我们可以使用装饰器模式来实现对扩容操作的权限判断、日志记录、缓存和限流。
public class ExpandPermissionDecorator implements UserService {
private UserService userService;
public ExpandPermissionDecorator(UserService userService) {
this.userService = userService;
}
@Override
public void expand(User user) {
// 权限判断
if (user.getPermission() != Permission.ADMIN) {
throw new RuntimeException("无权扩容");
}
// 业务逻辑
userService.expand(user);
}
}
public class ExpandLogDecorator implements UserService {
private UserService userService;
public ExpandLogDecorator(UserService userService) {
this.userService = userService;
}
@Override
public void expand(User user) {
// 日志记录
log.info("扩容操作:{}", user.getUsername());
// 业务逻辑
userService.expand(user);
}
}
public class ExpandCacheDecorator implements UserService {
private UserService userService;
public ExpandCacheDecorator(UserService userService) {
this.userService = userService;
}
@Override
public void expand(User user) {
// 缓存
cache.put(user.getId(), user);
// 业务逻辑
userService.expand(user);
}
}
public class ExpandLimiterDecorator implements UserService {
private UserService userService;
public ExpandLimiterDecorator(UserService userService) {
this.userService = userService;
}
@Override
public void expand(User user) {