责任链工厂改造
对于上面的请求链,我们也可以把这个关系维护到配置文件中或者一个枚举中。我将使用枚举来教会大家怎么动态的配置请求链并且将每个请求者形成一条调用链。
public enum GatewayEnum { // handlerId, 拦截者名称,全限定类名,preHandlerId,nextHandlerId API_HANDLER(new GatewayEntity(1, "api接口限流", "cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)), BLACKLIST_HANDLER(new GatewayEntity(2, "黑名单拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)), SESSION_HANDLER(new GatewayEntity(3, "用户会话拦截", "cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null)), ; GatewayEntity gatewayEntity; public GatewayEntity getGatewayEntity() { return gatewayEntity; } GatewayEnum(GatewayEntity gatewayEntity) { this.gatewayEntity = gatewayEntity; } } public class GatewayEntity { private String name; private String conference; private Integer handlerId; private Integer preHandlerId; private Integer nextHandlerId; } public interface GatewayDao { /** * 根据 handlerId 获取配置项 * @param handlerId * @return */ GatewayEntity getGatewayEntity(Integer handlerId); /** * 获取第一个处理者 * @return */ GatewayEntity getFirstGatewayEntity(); } public class GatewayImpl implements GatewayDao { /** * 初始化,将枚举中配置的handler初始化到map中,方便获取 */ private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>(); static { GatewayEnum[] values = GatewayEnum.values(); for (GatewayEnum value : values) { GatewayEntity gatewayEntity = value.getGatewayEntity(); gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity); } } @Override public GatewayEntity getGatewayEntity(Integer handlerId) { return gatewayEntityMap.get(handlerId); } @Override public GatewayEntity getFirstGatewayEntity() { for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) { GatewayEntity value = entry.getValue(); // 没有上一个handler的就是第一个 if (value.getPreHandlerId() == null) { return value; } } return null; } } public class GatewayHandlerEnumFactory { private static GatewayDao gatewayDao = new GatewayImpl(); // 提供静态方法,获取第一个handler public static GatewayHandler getFirstGatewayHandler() { GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity(); GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity); if (firstGatewayHandler == null) { return null; } GatewayEntity tempGatewayEntity = firstGatewayEntity; Integer nextHandlerId = null; GatewayHandler tempGatewayHandler = firstGatewayHandler; // 迭代遍历所有handler,以及将它们链接起来 while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) { GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId); GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity); tempGatewayHandler.setNext(gatewayHandler); tempGatewayHandler = gatewayHandler; tempGatewayEntity = gatewayEntity; } // 返回第一个handler return firstGatewayHandler; } /** * 反射实体化具体的处理者 * @param firstGatewayEntity * @return */ private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) { // 获取全限定类名 String className = firstGatewayEntity.getConference(); try { // 根据全限定类名,加载并初始化该类,即会初始化该类的静态段 Class<?> clazz = Class.forName(className); return (GatewayHandler) clazz.newInstance(); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } return null; } } public class GetewayClient { public static void main(String[] args) { GetewayHandler firstGetewayHandler = GetewayHandlerEnumFactory.getFirstGetewayHandler(); firstGetewayHandler.service(); } }
结语
设计模式有很多,责任链只是其中的一种,我觉得很有意思,非常值得一学。设计模式确实是一门艺术,仍需努力呀!
郭慕荣博客园