策略模式在springMVC和java中实际运用,

策略模式

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

策略模式的结构

策略模式是对算法的包装,是把使用算法的责任和算法本身分开。策略模式通常是把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。

策略模式涉及到三个角色:

1、环境角色

持有一个策略Strategy的引用

2、抽象策略角色

这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有具体策略类所需的接口

3、具体策略角色

包装了相关算法或行为

 

策略模式在java中的使用

在java中的一个非常经典的策略模式就是java中的Comparator接口,这就是属于抽象的策略角色,我们实现的该接口的实现类,也就是自定义的排序规则就是属于具体的策略角色。

我们在使用Arrays.sort()方法对我们自定义类型的对象进行排序的时候,往往会要求我们传入一个比较器,这个比较器就是具体的策略角色,也就是一个具体的算法,我们不用对原有的java中的Arrays.sort()方法进行任何的改变,直接传入不同的比较器就能使用不同的比较策略。

我们来想一下,如果没有策略模式,我们应该怎么来写这个代码?

那么在Arrays.sort()类中,我们就需要去频繁的改变其代码,每新增一种需要排序的类型,我们都要去其代码中新增一个if语句,然后添加具体的排序策略,这很明显就违背了一个非常基础的原则,也就是开闭原则。

 

策略模式的缺点是什么

缺点就在于我们在使用策略模式的对象的使用,需要知道每一种具体的策略。

就比如上面的Arrays.sort(),我们使用该方法对数组排序的时候,我们需要知道我们排序的数组的类型,以此来决定传入的具体的算法,如果没有使用策略模式,我们不需要知道任何的算法策略,直接传入一个数组,Arrays.sort()自动根据我们的类型进行排序。

 

使用了策略模式之后将策略的选择进行了迁移,本来需要在在Arrays.sort()方法中进行的判断我们转换到了我们客户端代码上来,使原有的Arrays.sort()类不需要进行任何的改变,但是又增加了我们客户端的使用成本,客户端需要知道所有的策略,每增加一种新的策略,我们还是需要去修改我们的代码。

 

工厂模式,单例模式,策略模式结合

其实可以把策略模式和单例,工厂模式和单例结合起来,完全的实现开闭原则,下面就用代码进行展示,还是以上面的Arrays.sort()为例子,我们自定义一些的Compator策略,使用一个工厂来管理这些策略。

两个比较器,也就是两个策略

public class IntCompareStrategy implements Comparator<Integer> {

    @Override
    public int compare(Integer o1, Integer o2) {
        return o1 - o2;
    }
}
public class DoubleCompareStrategy implements Comparator<Double> {

    @Override
    public int compare(Double o1, Double o2) {
        return (int) (o1 - o2);
    }
}

工厂类 

public class ComparatorStrategyFactory {
    /**
     * 工厂类统一管理所有的策略类
     */
    private HashMap<Class, Comparator> strategyMap = new HashMap<>();

    private ComparatorStrategyFactory() {
        if (Lazy.INSTANCE != null) {
            throw new RuntimeException("单例禁止创建多个实例");
        }
        init();
    }

    public static ComparatorStrategyFactory getInstance() {
        return Lazy.INSTANCE;
    }

    public <T> Comparator getStrategy(Class<T> clazz) {
        Comparator comparator = strategyMap.get(clazz);
        if (comparator == null) {
            if (Comparable.class.isAssignableFrom(clazz)) {
                comparator = strategyMap.get(Comparable.class);
            } else {
                comparator = strategyMap.get(Object.class);
            }
        }
        return comparator;
    }

    /**
     * 初始化所有的比较器
     */
    private void init() {
        /**
         * 这里可以修改成从配置文件中读取,或者使用去读取注解标识的类,以达到真正的开闭原则
         */
        strategyMap.put(Integer.class, new IntCompareStrategy());
        strategyMap.put(Double.class, new DoubleCompareStrategy());
        strategyMap.put(Comparable.class, new DefaultComparableStrategy());
        strategyMap.put(Object.class, new DefaultStrategy());
    }

    private static class Lazy {
        private static final ComparatorStrategyFactory INSTANCE = new ComparatorStrategyFactory();
    }
    
    // 默认的比较器
    private class DefaultStrategy implements Comparator<Object> {

        @Override
        public int compare(Object o1, Object o2) {
            return o1.hashCode() - o2.hashCode();
        }
    }
    // 默认的继承了Comparable接口的比较器
    private class DefaultComparableStrategy implements Comparator<Comparable> {

        @Override
        public int compare(Comparable o1, Comparable o2) {
            return o1.compareTo(o2);
        }
    }
}
public class StrategyTest {
    public static void main(String[] args) {
        Integer[] nums = new Integer[32];
        for (int i = 0; i < 32; i++) {
            nums[i] = (int) (Math.random() * 100);
        }
        System.out.println(Arrays.toString(nums));
        // 客户端在调用的时候不需要知道具体有什么策略类,把所有的策略集中在工厂进行管理,客户端只需要向工厂要策略就可以了
        Arrays.sort(nums, ComparatorStrategyFactory.getInstance().getStrategy(Integer.class));
        System.out.println(Arrays.toString(nums));
    }
}

核心代码就在工厂类里面,工厂统一管理所有的策略,客户端不需要知道任何的策略,这样在增加新的策略的时候我们也不需要去修改客户端的代码,因为客户端的代码一般比较核心,修改容易出现问题。工厂管理了所有的策略之后,可以通过多种方式获得策略,可以通过注解或者配置文件的方式来标识策略类,以达到真正的开闭原则。

 

上面的这种思想就来源于spirngMVC,springMVC中对Controller的处理就是上面的方式,每一个Controller里面的方法都相当于一个策略,DispatcherServlet这个类就相当于客户端,他需要使用很多的策略来应对不同的请求,这就是策略模式的一个非常好的应用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值