前言
之前有介绍过简易的责任链的实现方式,今天再介绍上一个责任链的升级版本
代码实现
通用接口类
public interface TestComponent {
void execute(Context context);
}
4个实现类
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class OneTestComponent implements TestComponent {
@Override
public void execute(Context context) {
log.info("one");
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class TwoTestComponent implements TestComponent {
@Override
public void execute(Context context) {
log.info("two");
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class ThreeTestComponent implements TestComponent {
@Override
public void execute(Context context) {
log.info("three");
}
}
上下文类
/**
* 用于传递上下文参数
*/
public class Context {
}
启动类,用于运行责任链
import java.util.List;
public class Test1Chain {
private List<TestComponent> testComponentList;
Test1Chain(List<TestComponent> testComponentList) {
this.testComponentList = testComponentList;
}
public void doExecute(Context context) {
for(TestComponent testComponent : testComponentList){
testComponent.execute(context);
}
}
}
import java.util.List;
public class Test2Chain {
private List<TestComponent> testComponentList;
Test2Chain(List<TestComponent> testComponentList) {
this.testComponentList = testComponentList;
}
public void doExecute(Context context) {
for(TestComponent testComponent : testComponentList){
testComponent.execute(context);
}
}
}
spring bean配置类。用于引入和配置责任链
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ClassUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class ChainConfig {
@Resource
private List<TestComponent> testComponents;
@Bean
public Test1Chain test1Chain() {
List<TestComponent> chain = new ArrayList<>();
chain.add(getComponent(OneTestComponent.class));
chain.add(getComponent(TwoTestComponent.class));
return new Test1Chain(chain);
}
@Bean
public Test2Chain test2Chain() {
List<TestComponent> chain = new ArrayList<>();
chain.add(getComponent(OneTestComponent.class));
chain.add(getComponent(ThreeTestComponent.class));
chain.add(getComponent(FourTestComponent.class));
return new Test2Chain(chain);
}
private <T extends TestComponent> T getComponent(Class<T> clazz) {
for (TestComponent c : testComponents) {
if (ClassUtils.isAssignable(c.getClass(), clazz)) {
TestComponent testComponent = c;
return testComponent == null ? null : (T) testComponent;
}
}
return null;
}
}
责任链使用启动
@Resource
Test1Chain test1Chain;
@Resource
Test2Chain test2Chain;
@Override
public Result<String> test22(String name) {
Context context = new Context();
test1Chain.doExecute(context);
test2Chain.doExecute(context);
return Result.success("success");
}
结果值
2020-11-02 20:03:25.503 INFO 21057 --- [nio-8761-exec-2] c.c.c.piplineHandler3.OneTestComponent : one
2020-11-02 20:03:25.503 INFO 21057 --- [nio-8761-exec-2] c.c.c.piplineHandler3.TwoTestComponent : two
2020-11-02 20:03:25.503 INFO 21057 --- [nio-8761-exec-2] c.c.c.piplineHandler3.OneTestComponent : one
2020-11-02 20:03:25.503 INFO 21057 --- [nio-8761-exec-2] c.c.c.p.ThreeTestComponent : three
2020-11-02 20:03:25.503 INFO 21057 --- [nio-8761-exec-2] c.c.c.piplineHandler3.FourTestComponent : four
说明
在ChainConfig中使用spring引入list,然后使用getComponent来获得对应的类,然后通过2个TestChain来执行责任链。然后可以看到第一个chain配置了one,two的顺序,第二个配置了one,three,four的顺序。这样每次如果有新的责任链,可以通过实现对应的接口,拼接成对应的chain来实现。
优化
其实在这个责任链上还可以做一层优化。目前一个责任链是在配置中直接配置好的。那么该怎么优化呢。chain的bean配置,可以用工厂来产生。那如何选择对应的类的。可以用策略模式,那么该怎么选择策略呢。可以用数据库或者某些条件来进行配置。那么就可以做到一个单子-工程-策略-责任链的一个循环了。
这部分的逻辑我也没有实现。等下次更新再实现这个优化版的终极责任链吧。end~