策略模式
描述:策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
1. StrategyContenxt类,进行策略的注册和和提供策略服务
package com.example.sk.strategy;
import com.example.sk.util.SpringContextHelper;
import java.util.HashMap;
public class StrategyContenxt {
// key
public static final String ROLE_TYPE = "role-type-";
// 策略映射map
private static final HashMap<String,Class<?>> providers = new HashMap<>();
// 提供给策略具体实现类的注册
public static void registerProvider(String subjectId,Class<?> provider){
providers.put(subjectId,provider);
}
// 返回策略映射的具体服务
public static Object getService(String subjectId){
Class<?> providerClazz = providers.get(subjectId);
return SpringContextHelper.getBean(providerClazz);
}
}
2. SpringContextHelper获取上下文实例,决定实施具体的策略
package com.example.sk.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* * 获取上下文中的bean实例
*/
@Component
public class SpringContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextHelper.applicationContext = applicationContext;
}
public static Object getBean(Class<?> clazz) throws BeansException {
return applicationContext.getBean(clazz);
}
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
}
3.TestService抽象策略角色,是对策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
package com.example.sk.service;
public interface TestService {
void test(Byte type);
}
4. 接口实现类选择具体的策略服务
package com.example.sk.service.impl;
import com.example.sk.service.TestService;
import com.example.sk.strategy.StrategyContenxt;
import org.springframework.stereotype.Service;
@Service("testService")
public class TestServiceImpl implements TestService {
@Override
public void test(Byte type) {
TestService service = (TestService) StrategyContenxt.getService(StrategyContenxt.ROLE_TYPE + type);
service.test(type);
}
}
5.TestAStrategyServiceImpl和TestBStrategyServiceImpl具体策略角色,即实现具体的算法和操作
package com.example.sk.service.impl;
import com.example.sk.constant.TypeEnums;
import com.example.sk.service.TestService;
import com.example.sk.strategy.StrategyContenxt;
import org.springframework.stereotype.Service;
@Service("testAStrategyService")
public class TestAStrategyServiceImpl implements TestService {
// 策略注册服务
static {
StrategyContenxt.registerProvider(StrategyContenxt.ROLE_TYPE+ TypeEnums.A.getType(),TestAStrategyServiceImpl.class);
}
@Override
public void test(Byte type) {
System.out.println("*************************************");
System.out.println("*************************************");
System.out.println("A代码");
System.out.println("*************************************");
System.out.println("*************************************");
}
}
package com.example.sk.service.impl;
import com.example.sk.constant.TypeEnums;
import com.example.sk.service.TestService;
import com.example.sk.strategy.StrategyContenxt;
import org.springframework.stereotype.Service;
@Service("testBStrategyService")
public class TestBStrategyServiceImpl implements TestService {
// 策略注册服务
static {
StrategyContenxt.registerProvider(StrategyContenxt.ROLE_TYPE+ TypeEnums.B.getType(),TestBStrategyServiceImpl.class);
}
@Override
public void test(Byte type) {
System.out.println("*************************************");
System.out.println("*************************************");
System.out.println("B代码");
System.out.println("*************************************");
System.out.println("*************************************");
}
}
6.DemoApplicationTests测试效果
package com.example.sk;
import com.example.sk.service.TestService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Autowired
@Qualifier("testService")
private TestService testService;
@Test
void contextLoads() {
testService.test((byte)1);
testService.test((byte)2);
}
}
6.优缺点
缺点:
1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类
2、代码中会产生非常多策略类,增加维护难度
优点:
1、算法可以自由切换
2、避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)
3、扩展性良好,增加一个策略只需实现接口即可.
7.源码里的策略模式
- Spring里的DispatcherServlet类
- jdk里的java.util.Collections调用sort方法,在调用的时候传入具体实现的比较算法,即策略,java.util.Collections.sort(List,Comparator)