返回

从实际需求看代理模式和装饰器模式

前端

问题引入

某天产品同学来找我。

产品同学🤵:有一个需求,需要对扩容操作加上权限判断。

加菲猫🐱:好的。

加菲猫🐱:改完了,看下。

相信很多同学都会这样写。

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) {