设计模式-装饰器模式
装饰器模式所解决的问题是,在不改变原来方法代码的情况下对方法进行修饰,从而丰富方法功能。
Spring架构中的装饰器模式
在Spring架构中,以线程池进行举例。
线程池
线程池是一个对线程集中管理的对象,集中管理线程的创建和销毁以及调度。线程池中的线程所要执行的,就是传入线程池的任务,线程池安排线程对任务进行执行。
任务就是编码者想要交给线程池来执行的代码块,如果编码者想要给任务加上一些修饰,线程池便提供了修饰类入口。编码者可以在任务执行前后进行日志打印,线程变量设置或释放。
一般线程池配置
import com.config.decorator.ThreadTaskDecorator;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class ThreadPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(100);
executor.setKeepAliveSeconds(60);
executor.setTaskDecorator(new ThreadTaskDecorator());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
线程装饰器
类ThreadTaskDecorator实现了接口TaskDecorator的decorate方法,对原任务进行了装饰。
import org.springframework.core.task.TaskDecorator;
public class ThreadTaskDecorator implements TaskDecorator {
@Override
public Runnable decorate(Runnable runnable) {
return () -> {
//前置
try {
//前置
runnable.run();//原任务
}finally {
//后置
}
//后置
};
}
}
线程池初始化–装饰器模式体现
初始化代码来自类ThreadPoolTaskExecutor.class,对无关代码进行了折叠。
protected ExecutorService initializeExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
...
ThreadPoolExecutor executor = new ThreadPoolExecutor(this.corePoolSize, this.maxPoolSize, (long)this.keepAliveSeconds, TimeUnit.SECONDS, queue, threadFactory, rejectedExecutionHandler) {
public void execute(Runnable command) {
Runnable decorated = command;
if (ThreadPoolTaskExecutor.this.taskDecorator != null) {
decorated = ThreadPoolTaskExecutor.this.taskDecorator.decorate(command);
if (decorated != command) {
ThreadPoolTaskExecutor.this.decoratedTaskMap.put(decorated, command);
}
}
super.execute(decorated);
}
.
.
.
};
.
.
.
return executor;
}
从初始化代码中可以看见,在创建executor时对ThreadPoolExecutor的父类接口Executor中的execute方法进行了实现,其中就是判断任务装饰器taskDecorator不为空的情况下,调用taskDecorator对象的decorate方法对command即原任务进行装饰。这里的taskDecorator对象就是我们前面通过nre ThreadTaskDecorator()
传递进去的,在线程池初始化的时候被调用到decorate,对原任务进行装饰。
装饰器模式是将装饰和被装饰者进行分离,装饰和被装饰者相互独立。这种分离的方式使得,一种装饰只需要实现一次,便可以重复使用。这是代码复用的很好方案。