策略模式之if else代码优化

梦想与她 提交于 2020-01-16 00:31:48
一、概念

  策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

  • if else使用

    if (pageLevel = "1") {
    	// 发送get请求
    } else if(pageLevel = "2") {
    	// 发送post请求
    } else {
    	// 
    }
    

  这种if else代码块中,代码很难维护也很也不够美观,那么我们可以使用策略模式来处理这种情况。

二、案例

  简单来讲就是定义一个接口,然后有多个实现类,每种实现类封装了一种行为。然后根据条件的不同选择不同的实现类。

  • 抽象业务接口

    public interface SendRequestCenter {
    
        public abstract void solve(String param);
    
        public abstract String[] supports();
    }
    
  • 接口实现类,举例:一个发送get请求,一个发送post请求

    import org.springframework.stereotype.Component;
    
    @Component
    public class SendPostRequestSolver implements SendRequestCenter {
    
        @Override
        public void solve(String param) {
            System.out.println("参数是" + param + "的post请求已经发送了。。");
        }
    
        @Override
        public String[] supports() {
            return new String[]{RequestType.HTTP_POST};
        }
    }
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class SendGetRequestSolver implements SendRequestCenter {
    
        @Override
        public void solve(String id) {
            System.out.println("参数是" + id + "的get请求已经发送了。。");
        }
    
        @Override
        public String[] supports() {
            return new String[]{RequestType.HTTP_GET};
        }
    }
    
  • 常量类

    public class RequestType {
        public static String HTTP_GET = "1";
        public static String HTTP_POST = "2";
    }
    
  • 将业务处理器和其支持处理的类型放到一个容器中,Map就是最常用的容器,使用spring的上下文存储信息

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.PostConstruct;
    import java.util.HashMap;
    import java.util.Map;
    
    @Component
    public class RequestSolverChooser implements ApplicationContextAware {
    
        private ApplicationContext context;
        private Map<String, SendRequestCenter> chooseMap = new HashMap<>();
    
        public SendRequestCenter choose(String type) {
            return chooseMap.get(type);
        }
    
        //被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。
        //被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
        @PostConstruct
        public void register() {
            Map<String, SendRequestCenter> solverMap = context.getBeansOfType(SendRequestCenter.class);
            for (SendRequestCenter solver : solverMap.values()) {
                for (String support : solver.supports()) {
                    chooseMap.put(support, solver);
                }
            }
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.context = applicationContext;
        }
    }
    
    
  • 另一种处理方式是使用工厂模式和策略模式相结合,工厂采用单例模式

    import java.util.HashMap;
    import java.util.Map;
    
    public class StrategyFactory {
    
        private static StrategyFactory factory = new StrategyFactory();
        private StrategyFactory(){
        }
        private static Map<String,SendRequestCenter> strategyMap = new HashMap<>();
        static{
            strategyMap.put(RequestType.HTTP_GET, new SendGetRequestSolver());
            strategyMap.put(RequestType.HTTP_POST, new SendPostRequestSolver());
        }
        public SendRequestCenter creator(String pType){
            return strategyMap.get(pType);
        }
        public static StrategyFactory getInstance(){
            return factory;
        }
    }
    
  • 在单元测试中进行测试

    @Autowired
    private RequestSolverChooser chooser;
    //使用spring上下文测试
    @Test
    public void test() throws Exception {
    	//准备数据
    	String taskType = RequestType.HTTP_GET;
    	//获取任务类型对应的solver
    	SendRequestCenter solver = chooser.choose(taskType);
    	if (solver == null) {
    		throw new RuntimeException("任务类型暂时无法处理!");
    	}
    	//调用不同solver的方法进行处理
    	solver.solve("\"百度\"");
    }
    //使用工厂模式测试
    @Test
    public void test2() throws Exception {
    	String taskType = RequestType.HTTP_POST;
    	SendRequestCenter solver = StrategyFactory.getInstance().creator(taskType);
    	if (solver == null) {
    		throw new RuntimeException("任务类型暂时无法处理!");
    	}
    	//调用不同solver的方法进行处理
    	solver.solve("\"腾讯\"");
    }
    
  • 测试结果1

    2020-01-15 15:25:46.752  INFO 2120 --- [           main] c.w.collection.DemoApplicationTests      : No active profile set, falling back to default profiles: default
    2020-01-15 15:25:47.574  INFO 2120 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2020-01-15 15:25:47.766  INFO 2120 --- [           main] c.w.collection.DemoApplicationTests      : Started DemoApplicationTests in 1.255 seconds (JVM running for 2.254)
    参数是"百度"的get请求已经发送了。。
    2020-01-15 15:25:47.923  INFO 2120 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
    
  • 测试结果2

    2020-01-15 15:26:30.860  INFO 4640 --- [           main] c.w.collection.DemoApplicationTests      : No active profile set, falling back to default profiles: default
    2020-01-15 15:26:31.689  INFO 4640 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
    2020-01-15 15:26:31.867  INFO 4640 --- [           main] c.w.collection.DemoApplicationTests      : Started DemoApplicationTests in 1.274 seconds (JVM running for 2.273)
    参数是"腾讯"的post请求已经发送了。。
    2020-01-15 15:26:32.013  INFO 4640 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
    

参考博客:https://blog.csdn.net/qq_22343483/article/details/100195157

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!