持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
策略模式说白了就是简单的匹配
Map<Integer,doAction> map = new HashMap<>();
map.put(1, doAction1());
map.put(2, doAction2());
map.put(3, doAction3());
根据不同的参数,从map中取出对应的数据然后进行相应的操作
doAction1() = map.get(1);
你传个1参数,那这个时候执行的不就是 doAction1() 方法吗
上面其实就是策略模式最简单的实现想法
- 用 Lambda 的形式写个策略模式
public class Test {
private static Map<String, Consumer<String>> FUNC_MAP = new HashMap<>();
private static String MAN = "man";
private static String WOMAN = "woman";
static {
FUNC_MAP.put(MAN, person -> {
System.out.println(person + "男");
});
FUNC_MAP.put(WOMAN, person -> {
System.out.println(person + "女");
});
}
public static void main(String[] args) {
Person person = new Person();
person.setGender(MAN);
person.setName("张三");
FUNC_MAP.get(person.getGender()).accept(person.getName());
}
}
@Data
class Person {
private String gender;
private String name;
}
- 简单3步,使用 Spring 中 @Autowired 和 @Component 注解实现一个 策略+工厂模式
先看下对外调用的接口(controller)
@Resource
private QueryUserFactory queryUserFactory;
@GetMapping(value = "/queryUser")
public User queryUser(int type, Long userId) {
QueryUserHandler handler = queryUserFactory.getHandlerMap(type);
return handler.queryUserById(userId);
}
- 第一步:先新建个 handler 接口类
这是个接口类,不需要任何注解
package com.example.demo.strategy;
import com.example.demo.User;
public interface QueryUserHandler {
/**
* 查询用户信息
*
* @param id 用户id
* @return 用户信息
*/
User queryUserById(Long id);
}
- 第二步:实现对应的接口类
package com.example.demo.strategy.impl;
import com.example.demo.User;
import com.example.demo.strategy.QueryUserHandler;
import org.springframework.stereotype.Component;
@Component
public class AppUserImpl implements QueryUserHandler {
@Override
public User queryUserById(Long id) {
return null;
}
}
package com.example.demo.strategy.impl;
import com.example.demo.User;
import com.example.demo.strategy.QueryUserHandler;
import org.springframework.stereotype.Component;
@Component
public class PcUserImpl implements QueryUserHandler {
@Override
public User queryUserById(Long id) {
return null;
}
}
- 第三步:再建个 factory 工厂类
这个类上需要加上 @Component 注解,map 变量上要加上 @Autowired 注解
package com.example.demo.strategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class QueryUserFactory {
@Autowired
private Map<String, QueryUserHandler> handlerMap;
public QueryUserHandler getHandlerMap(int type) {
return handlerMap.get(type);
}
}
这里 @Autowired 注解,会把所有实现 QueryUserHandler 接口的类,全部自动注入到这个map中,比如上面两个实现 QueryUserHandler 接口的类
如果不指定 bean name,Spring 默认生成的 bean name 就是类名,开头字母小写的
如果你打断点看 map 内容的话,应该是有两条数据
key: appUserImpl value: AppUserImpl.class
key: pcUserImpl value: PcUserImpl.class
但是这个 getHandlerMap() 方法就有问题了,key 是 string 类型,传进来个 int 类型的怎么能行呢
这个简单啊,让前端改成传 string 类型的不就行了吗
或者你自己再写个 int 转 string 的方法
public class TypeToAlias {
private static final Map<Integer, String> ALIAS_MAP;
static {
ALIAS_MAP = Maps.newHashMap();
ALIAS_MAP.put(1, "appUserImpl");
ALIAS_MAP.put(2, "pcUserImpl");
}
public static String of(int type) {
return ALIAS_MAP.get(type);
}
}
然后改下 getHandlerMap 方法
public QueryUserHandler getHandlerMap(int type) {
String beanName = TypeToAlias.of(type);
return handlerMap.get(beanName);
}
这不就ok了
简单吧,这不比 if...else 逼格高多了