基于spring bean生命周期实现策略模式

场景: 假设目前我们需要根据客户的类型来生成不同的客户

if(type == "a") {
    userService.createAUser()
} else if (type == "b") {
    userService.createBUser()
}

简单的if...else虽然可以搞定但是不够优雅,我们使用策略模式来进行重构

先定义userService业务处理接口如下:

public interface UserService {
    void createUser(String type);
}

方案1:sprinbg bean注入方式

public interface UserHandle {
    R execute(T t);
}

根据不同的类型实现处理类

@Service("aUserHandle")
public class AUserHandleImpl implements UserHandle {
    @Override
    public String execute(String s) {
        return "[aUserHandle] type = " + s;
    }
}
@Service("bUserHandle")
public class BUserHandleImpl implements UserHandle {
    @Override
    public String execute(String s) {
        return "[bUserHandle] type = " + s;
    }
}

将所有的处理类注册到contxt实现策略选择

@Component
public class OneUserConctext {
    private Map userServiceMap = new HashMap<>();

    @Resource(name = "aUserHandle")
    private UserHandle aUserHandle;

    @Resource(name = "bUserHandle")
    private UserHandle bUserHandle;

    @PostConstruct
    public void init() {
        userServiceMap.put("a", aUserHandle);
        userServiceMap.put("b", bUserHandle);
    }

    public UserHandle getHandle(String type) {
        if (StringUtils.isEmpty(type)) {
            return null;
        }
        return userServiceMap.get(type);
    }
}

userService业务处理逻辑根据不同的type选择具体的处理bean

@Service("oneUserService")
public class OneUserServiceImpl implements UserService {
    @Resource
    private OneUserConctext oneUserConctext;

    @Override
    public void createUser(String type) {
        UserHandle handle = oneUserConctext.getHandle(type);
        if (null == handle) {
            throw new RuntimeException("not find handle");
        }
        System.out.println(handle.execute(type));
    }
}

这种方案的实现比较简单,当然也可以使用xml配置的方式,大致也如此。但是不够优雅,有新的handle bean实现都必须手动配置,下面的方案我们都会结合spring来实现,关于spring bean生命周期自行学习

2. InitializingBean实现策略模式

 先定义业务逻辑执行接口

public interface TwoUserHandle {
    R execute(T t);
    boolean accept(T t);
}

策略选择逻辑的实现

@Component
public class TwoUserContext {
    //策略beans容器
    private List userHandleList = new ArrayList<>();

    public void regisiter(TwoUserHandle handle) {
        userHandleList.add(handle);
    }

    //选择具体的handle处理
    public TwoUserHandle getHandle(String type) {
        if (StringUtils.isEmpty(type)) {
            return null;
        }
        return userHandleList.stream().filter(h -> h.accept(type)).findFirst().orElse(null);
    }
}
public abstract class AbstracrUserHandle implements TwoUserHandle, InitializingBean {
    @Resource
    private TwoUserContext twoUserContext;

    @Override
    public void afterPropertiesSet() {
        //在这里注册实现bean
        twoUserContext.regisiter(this);
    }
}
@Service("aTwoUserHandle")
public class ATwoUserHandleImpl extends AbstracrUserHandle {
    @Override
    public String execute(String s) {
        return "[aTwoUserHandle] type = " + s;
    }

    @Override
    public boolean accept(String s) {
        return "a".equals(s);
    }
}
@Service("bTwoUserHandle")
public class BTwoUserHandleImpl extends AbstracrUserHandle {
    @Override
    public String execute(String s) {
        return "[bTwoUserHandle] type = " + s;
    }

    @Override
    public boolean accept(String s) {
        return "b".equals(s);
    }
}

业务接口根据类型选择具体策略bean

@Service("twoUserService")
public class TwoUserService implements UserService {
    @Resource
    private TwoUserContext twoUserContext;
    @Override
    public void createUser(String type) {
        TwoUserHandle handle = twoUserContext.getHandle(type);
        if (null == handle) {
            throw new RuntimeException("not found handle");
        }
        System.out.println(handle.execute(type));
    }
}

 

3. 注解 + BeanFactoryPostProcessor 

我们先实现一个注解对应一个处理逻辑

先定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface HandleType {
    String value() default "";
}

然后实现处理beans容易注入类

@Component
public class ThreeUserContext implements BeanFactoryPostProcessor {
    //beans容器map
    private Map handleMap = new HashMap<>();

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //根据注解找到处理bean,注入容器
        Map handBeans = configurableListableBeanFactory.getBeansWithAnnotation(HandleType.class);
        Optional.ofNullable(handBeans)
                .orElse(Collections.emptyMap())
                .forEach((name, bean) -> {
                    Class aClass = bean.getClass();
                    HandleType annotation = aClass.getAnnotation(HandleType.class);
                    handleMap.put(annotation.value(), (ThreeUserHandle)bean);
            });
    }
    
    //根据类型选择业务处理bean
    public ThreeUserHandle getHandle(String type) {
        if (StringUtils.isEmpty(type)) {
            return null;
        }
        return handleMap.get(type);
    }
}

业务接口及具体实现

public interface ThreeUserHandle {
    R execute(T t);
}
@HandleType("a")
@Service("aThreeUserHandle")
public class AThreeUserHandleImpl implements ThreeUserHandle {
    @Override
    public String execute(String s) {
        return "[aThreeUserHandle] type = " + s;
    }
}
@HandleType("b")
@Service("bThreeUserHandle")
public class BThreeUserHandleImpl implements ThreeUserHandle {
    @Override
    public String execute(String s) {
        return "[bThreeUserHandle] type = " + s;
    }
}

userService调用

@Service("threeUserService")
public class ThreeUserService implements UserService {
    @Resource
    private ThreeUserContext threeUserContext;
    @Override
    public void createUser(String type) {
        ThreeUserHandle handle = threeUserContext.getHandle(type);
        if (null == handle) {
            throw new RuntimeException("not found handle");
        }
        System.out.println(handle.execute(type));
    }
}

4. 注解 + BeanPostProcessor

上面的实现方式每个注解对应一个处理bean,下面要实现一个注解对应多个bean实现的方式

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface FourHandleTypes {
    //bean name
    String[] values() default {};
}

实现一个通用的处理选择bean

public class AbstraceHandle{
    //处理beans容器
    private List handleList;

    public void setHandleList(List handleList) {
        this.handleList = handleList;
    }
    
    //执行业务逻辑
    public R execute(T t) {
        //获取逻辑处理bean
        FourUserHandle handle = getHandle(t);
        if (handle == null) {
            throw new RuntimeException("can not find handle");
        }
        return (R) handle.execute(t);
    }


    //具体业务bean选择
    private FourUserHandle getHandle(T t) {
        if (handleList == null) {
            return null;
        }
        return handleList.stream().filter(h -> h.accpet(t)).findFirst().orElse(null);
    }
}

实现一个具体的处理beans容器

@FourHandleTypes(values = {
        "aFourUserHandle",
        "bFourUserHandle"
})
@Component
public class FourHandleContext extends AbstraceHandle {
}

在BeanPostProcessor中获取到注解配置的beans,并根据spring beanName找到真实bean注入到策略beans容器

@Component
public class FourHandleBeanProcessor implements BeanPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof AbstraceHandle && bean.getClass().isAnnotationPresent(FourHandleTypes.class)) {
            Class aClass = bean.getClass();
            //获取注解配置beans并从spring中根据beanName获取到bean注入到策略beans
            FourHandleTypes annotation = aClass.getAnnotation(FourHandleTypes.class);
            String[] values = annotation.values();
            if (null != values && values.length > 0) {
                List handles = Arrays.stream(values).map(name -> {
                    FourUserHandle handle = (FourUserHandle) applicationContext.getBean(name);
                    return handle;
                }).collect(Collectors.toList());
                ((AbstraceHandle)bean).setHandleList(handles);
            }
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

策略接口及实现

public interface FourUserHandle {
    R execute(T t);
    boolean accpet(T t);
}
@Service("aFourUserHandle")
public class AFourUserHandleImpl implements FourUserHandle {
    @Override
    public String execute(String s) {
        return "[aFourUserHandle] type = " + s;
    }

    @Override
    public boolean accpet(String s) {
        return "a".equals(s);
    }
}
@Service("bFourUserHandle")
public class BFourUserHandleImpl implements FourUserHandle{
    @Override
    public String execute(String s) {
        return "[bFourUserHandle] type = "+s;
    }

    @Override
    public boolean accpet(String s) {
        return "b".equals(s);
    }
}

业务逻辑调用

@Service("fourUserService")
public class FourUserService implements UserService {
    @Resource
    private FourHandleContext fourHandleContext;

    @Override
    public void createUser(String type) {
        System.out.println(fourHandleContext.execute(type));
    }
}

 

通过策略模式可以减少if...else代码开发是程序可读性更强,再结合spring bean生命周期实现策略模式使得实现更加灵活

你可能感兴趣的:(设计模式)