场景: 假设目前我们需要根据客户的类型来生成不同的客户
if(type == "a") {
userService.createAUser()
} else if (type == "b") {
userService.createBUser()
}
简单的if...else虽然可以搞定但是不够优雅,我们使用策略模式来进行重构
先定义userService业务处理接口如下:
public interface UserService {
void createUser(String type);
}
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生命周期自行学习
先定义业务逻辑执行接口
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));
}
}
我们先实现一个注解对应一个处理逻辑
先定义注解
@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));
}
}
上面的实现方式每个注解对应一个处理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生命周期实现策略模式使得实现更加灵活