策略模式目的是取代if...else...的写法,但是策略模式一般需要定义一个接口+多个实现类,然后使用枚举类(实现享元模式)或者Map(实现享元模式)来维护type:实现类的关系。但是很给人一种很重的感觉(因为写法有点繁琐,接口类+多个实现类)。
可以借助lambda中Function+Map,使用Map+内部类来实现轻量级的策略模式。
public class TestBiFunction {
//1. MAP的value是内部类,即BiFunction接口实现类。免去了要定义一个接口类的工作。
//2. BiFunction中基础类型不能表示出字段的含义,可借助/*xxx*/注解来表示含义。
private static final ConcurrentMap<Long/*type*/, BiFunction<Long/*a*/, Long/*b*/, User>> MAP =
Maps.newConcurrentMap();
//spring中,可以使用@PostConstruct注解来完成加载。
{
MAP.put(1L, (a, b) -> getSimpleUser(a, b));
MAP.put(2L, this::getUser);
MAP.put(3L, this::getComplexUser);
}
public static void main(String[] args) {
TestBiFunction testBiFunction = new TestBiFunction();
System.out.println(testBiFunction.getUserByType(1L, 1001L, 1002L));
System.out.println(testBiFunction.getUserByType(2L, 1001L, 1002L));
System.out.println(testBiFunction.getUserByType(3L, 1001L, 1002L));
}
/**
* 根据type来选择策略模式,
* 入参和出参必须是有要求。
*/
public User getUserByType(Long type, Long a, Long b) {
return MAP.get(type).apply(a, b);
}
/**
* spring中,可以此方法中 使用外部类中定义的IOC容器中的bean
*/
public User getSimpleUser(Long a, Long b) {
User user = new User();
user.setName("simple user" + a + b);
return user;
}
public User getUser(Long a, Long b) {
User user = new User();
user.setName("user" + a + b);
return user;
}
public User getComplexUser(Long a, Long b) {
User user = new User();
user.setName("complex user" + a + b);
return user;
}
}
其实原理就是借助lambda表达式中已经定义好的接口类(Function、BiFunction),然后MAP中value的值实际是实现Function的匿名内部类,实现的策略方法是apply方法。
省去了定义策略方法的步骤。
这样就可以完成策略子类的维护与实现。