1 装饰器模式介绍
装饰器模式是一种结构型设计模式,它允许你在运行时通过将对象包装在装饰器类的对象中来扩展一个对象的功能。
装饰器模式可以动态地为对象添加新的功能,而无需修改原始对象代码。这种模式通过创建一系列包装器来实现递归地嵌套对象来扩展功能。每个包装器都通过增加一些新的行为或修改原始对象的行为来扩展对象的功能。
📌 与代理模式区别
- 装饰器模式与前面介绍的代理模式在结构上是一样的。对装饰器模式来说,装饰者和被装饰者都实现同一个接口或抽象类;对代理模式来说,代理类和被代理的类都实现同一个接口或抽象类,在结构上确实没有区别。
- 但是它们的作用不同。装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能,增强后你还是你,只是被强化了;代理模式强调要让别人帮你去做事情,以及添加一些与你本身的业务没有太多关系的事情(记录日志、设置缓存等),重点在于让别人帮你做。
📌 优缺点
- 优点:动态地扩展对象的功能,避免了使用继承时子类的数量庞大、继承结构复杂的问题,同时保持类结构简单清晰。
- 缺点:可能产生过多的小对象,过多的装饰器会使程序变得复杂难懂。
2 装饰器模式实现
以用户服务的查询为例:
📌 1.定义用户服务
/**
* 用户服务
*/
public interface UserService {
/**
* 查询
*/
public void query();
}
📌 2.实现用户服务
/**
* 用户服务实现类
*/
public class UserServiceImpl implements UserService {
@Override
public void query() {
System.out.println("查询了一个用户");
}
}
📌 3.定义装饰器
/**
* 装饰器
*/
public class Decorator implements UserService{
/**
* 用户服务<br>
* 定义为 protected 是为了方便子类的后置处理器使用
*/
protected UserService userService;
/**
* 装饰用户服务
* @param userService 用户服务
*/
public Decorator(UserService userService) {
this.userService = userService;
}
@Override
public void query() {
userService.query();
}
}
📌 4.定义装饰器后置处理器
/**
* 装饰器后置处理器
*/
public class DecoratorPostProcessor extends Decorator{
/**
* 使用父类的装饰器装饰用户服务
* @param userService 用户服务
*/
public DecoratorPostProcessor(UserService userService) {
super(userService);
}
@Override
public void query() {
userService.query();
// 后置处理
System.out.println("查找字典表给性别赋值");
}
}
📌 5.调用
// 装饰用户服务实现类(注意,这里需要用装饰器后置处理器装饰,因为后置处理的业务逻辑写在里面)
Decorator decorator = new DecoratorPostProcessor(new UserServiceImpl());
// 调用装饰后的查询方法
decorator.query();
控制台输出结果:
📌 6.嵌套使用
在开发场景中,有时候一次后置处理并不能得到预期的数据(比如数字转化为编码,编码再转化为名称),需要再次处理,此时再去定义一个装饰器是没有必要的,可以嵌套使用。
// 嵌套使用
DecoratorPostProcessor decorator1 = new DecoratorPostProcessor(decorator);
decorator1.query();
执行main方法: