⼿把⼿教你如何实现策略模式!两种实现⽅式哟
什么是策略模式
在策略模式(Strategy Pattern)中,⼀个类的⾏为或其算法可以在运⾏时更改。这种类型的设计模式属于⾏为型模式。 在策略模式中,我们创建表⽰各种策略的对象和⼀个⾏为随着策略对象改变⽽改变的 context 对象。策略对象改变 context 对象的执⾏算法。
意图:定义⼀系列的算法,把它们⼀个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使⽤ if...else 所带来的复杂和难以维护。
何时使⽤:⼀个系统有许多许多类,⽽区分它们的只是他们直接的⾏为。
如何解决:将这些算法封装成⼀个⼀个的类,任意地替换。
关键代码:实现同⼀个接⼝。
应⽤实例: 1、诸葛亮的锦囊妙计,每⼀个锦囊就是⼀个策略。 2、旅⾏的出游⽅式,选择骑⾃⾏车、坐汽车,每⼀种旅⾏⽅式都是⼀个策略。 3、JAVA AWT 中的 LayoutManager。
优点: 1、算法可以⾃由切换。 2、避免使⽤多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
使⽤场景: 1、如果在⼀个系统⾥⾯有许多类,它们之间的区别仅在于它们的⾏为,那么使⽤策略模式可以动态地让⼀个对象在许多⾏为中选择⼀种⾏为。 2、⼀个系统需要动态地在⼏种算法中选择⼀种。 3、如果⼀个对象有很多的⾏为,如果不⽤恰当的模式,这些⾏为就只好使⽤多重的条件选择语句来实现。
注意事项:如果⼀个系统的策略多于四个,就需要考虑使⽤混合模式,解决策略类膨胀的问题。
策略模式第⼀种实现⽅式
讲解
策略模式
通过handler进⾏动态选择具体处理的实现类
handlerType: ⽤来标识具体不同的实现。
AbstractHandler: 抽象类,抽象⽅法,对外提供的统⼀实现⽅法。
HandlerContext:核⼼处理所有的适配器,初始化完成之后,将所有的适配器保存到该对象中,该对象的单例模式。需要的时候,根据标识去获取对应的hand getInstance: 获取适配器的具体实现类,如果缓存中是空的,那就通过包扫描到的所有适配器名字,获取到对应的类,然后获取类上⾯的注解。注解内容当做 HandlerProcessor:该类继承了BeanFactoryPostProcessor,项⽬启动的时候,扫描指定包下⾯的所有类,获取有指定注解的所有类,然后将类放到list中,然 MyClassPathDefinitonScanner:⾃定义的包扫描器
ScannerUtil:包扫描⼯具类,使⽤该⽅法进⾏扫描包
SpringContextUtil: spring 的上下⽂对象⼯具类
TestHandler:测试具体实现的handler适配器
运⾏顺序,⽅式:
1、HandlerProcessor 执⾏该类,调⽤包扫描⼯具类 ScannerUtil 扫描指定包路径下的所有包。
2、ScannerUtil ⼯具类⾥⾯使⽤⾃定义的扫描⼯具 MyClassPathDefinitonScanner 进⾏扫描
3、将扫描的内容整合,获取到java bean的名字,保存到map中,返回给 HandlerProcessor
4、HandlerProcessor 将内容整合成list,将list保存到 HandlerContext 中。
5、单元测试中,⾃动装载单例的HandlerContext
6、HandlerContext通过传过来的type值进⾏获取到对应具体的TestHandler实现
6.1、HandlerContext判断缓存是否为空
6.1.1、如果为空,遍历list,获取到所有的bean对象的className
6.1.2、使⽤spring上下⽂对象⼯具类,通过className获取到具体的bean
6.1.3、读取bean对象的类注解。
6.1.4、注解值为key,bean为v,创建缓存对象。
6.2、根据传过来的值,去缓存中获取具体的bean对象。
6.3、将bean对象以⽗对象的形式返回出去。
7、获取到AbstractHandler⽗对象,然后调⽤抽象⽅法,⾃动调⽤到⼦类实现。
直接上⼲货
HandlerProcessor
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.fig.BeanFactoryPostProcessor;
import org.springframework.fig.ConfigurableListableBeanFactory;
import t.annotation.Lazy;
import org.springframework.stereotype.Component;
llect.Lists;
import java.util.List;
import java.util.Map;
@Component
@SuppressWarnings("unchecked")
@Lazy
public class HandlerProcessor implements BeanFactoryPostProcessor {
private static final Logger log = Logger(HandlerProcessor.class);
private static final String HANDLER_PACKAGE = "ampleall*";
public static String test = "1";
/**
* 扫描@HandlerType ,初始化HandlerContext,将其注册到spring容器
* @param configurableListableBeanFactory
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { log.info(test);
List<String> handlerList = wArrayListWithExpectedSize(3);
//TODO 扫描指定的包,获取类上⾯的注解根据注解不同,将不同的类放到map中
Map<String, Object> result = ScannerUtil.scanner(HandlerType.class, HANDLER_PACKAGE);
int size = Integer.("size").toString());
log.info("扫描到{}个包", size);
List<String> data = (List<String>) ("data");
for (String beanName : data) {
handlerList.add(beanName);
}
log.info("增加{}个handler", handlerList.size());
HandlerContext handlerContext = new HandlerContext(handlerList);
}
}
ScannerUtil
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import t.support.GenericApplicationContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ScannerUtil {
private static final Logger log = Logger(ScannerUtil.class);
public static Map<String, Object> scanner(Class annotation, basePackage) {
Map<String, Object> result = new HashMap<>();
try {
GenericApplicationContext context = new GenericApplicationContext();
MyClassPathDefinitonScanner myClassPathDefinitonScanner = new MyClassPathDefinitonScanner(context, annotation); // 注册过滤器
int beanCount = myClassPathDefinitonScanner.scan(basePackage);
String[] beanDefinitionNames = BeanDefinitionNames();
List<String> data = new ArrayList<>();
for (int i = 0; i < beanDefinitionNames.length; i++) {
if (!beanDefinitionNames[i].startsWith("t")) {
data.add(beanDefinitionNames[i]);
}
}
result.put("beanCount", beanCount);
result.put("beanDefinitionNames", beanDefinitionNames);
result.put("size", data.size());
result.put("data", data);
} catch (Exception e) {
<(StackTrace()));
}
return result;
}
}
MyClassPathDefinitonScanner
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import t.annotation.ClassPathBeanDefinitionScanner;
import ype.filter.AnnotationTypeFilter;
import java.lang.annotation.Annotation;
public class MyClassPathDefinitonScanner extends ClassPathBeanDefinitionScanner {
private Class type;
public MyClassPathDefinitonScanner(BeanDefinitionRegistry registry, Class<? extends Annotation> type){
单例模式的几种实现方式super(registry,false);
}
/**
* 注册过滤器
*/
public void registerTypeFilter(){
addIncludeFilter(new AnnotationTypeFilter(type));
}
}
HandlerContext
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HandlerContext {
private static final Logger log = Logger(HandlerContext.class);
private Map<String, Class> handlerMap;
private List<String> handlerList;
public HandlerContext(List<String> handlerList) {
log.info("初始化HandlerContext");
this.handlerList = handlerList;
}
public AbstractHandler getInstance(String type) {
if (handlerMap == null) {
log.info("handlerMap为空,初始化");
handlerMap = new HashMap<>();
for (String beanName : handlerList) {
Class clazz = Bean(beanName).getClass();
handlerMap.put(getAnnotation(clazz), clazz);
}
}else{
log.info("handlerMap不为空,不需要初始化");
}
Class clazz = (type);
if (clazz == null) {
throw new RuntimeException("没有到该实例");
}
return (AbstractHandler) Bean(clazz);
}
public static String getAnnotation(Class clazz) {
HandlerType handlerType = (HandlerType) Annotation(HandlerType.class); if (handlerType != null) {
return handlerType.value();
} else {
return "";
}
}
}
AbstractHandler
public abstract class AbstractHandler {
public abstract String handler(String type);
}
HandlerType
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论