10、【设计模式】策略模式
在软件领域中,设计模式作为一种经典的开发实践常常需要我们去深入的理解,而策略模式作为设计模式的一种,使用频率也是相对来说比较高的,在Java中,当我们学习TreeSet集合的时候,就采用了经典的策略模式的思想,本文主要讲解策略模式。
概念
其思想是针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能。
特点
策略模式体现了面向对象程序设计中非常重要的两个原则:
封装变化的概念。编程中使用接口,而不是使用的是具体的实现类(面向接口编程)。
举例:我们就以Java中的TreeSet为例,TreeSet仅仅知道它只是接收一个Comparator这种接口类型,但是具体是哪种实现类,TreeSet并不关心,实现类在真正的传入TreeSet之前,TreeSet本身是不知道的,所以我们可以自己去实现Comparator接口,然后在实现类里面去封装好我们自己的规则(这里的规则你可以当做是算法),比如说我们要实现对一个集合的元素排序,但是到底是要升序排序还是降序排序,这个完全由我们来去控制,我们可以把这种变化的内容封装到自己的实现类中,真正运行的时候才知道具体的实现。
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130031869-1026893488.jpg)
组成
抽象策略角色这个是一个抽象的角色,通常情况下使用接口或者抽象类去实现。对比来说,就是我们的Comparator接口。具体策略角色包装了具体的算法和行为。对比来说,就是实现了Comparator接口的实现一组实现类。环境角色内部会持有一个抽象角色的引用,给客户端调用。对比来说,就是我们的TreeSet类。说明:TreeSet内部一定会有一个策略类的一个成员变量,这样做的目的在于可以当我们在去创建TreeSet对象的时候,可以接收我们向TreeSet类中传递的具体的策略类。
编写步骤
定义抽象策略角色(为策略对象定义一个公共的接口)编写具体策略角色(实际上就是实现上面定义的公共接口)定义环境角色,内部持有一个策略类的引用
案例
实现一个加减乘除的功能。
1、定义抽象策略角色
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130111768-1790780096.jpg)
2、定义具体策略角色(本例子仅仅演示,只是定义加、减两种具体策略)
加法策略:
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130136903-1670451558.jpg)
减法策略:
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130141957-973319700.jpg)
3、环境角色
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130146958-875346871.jpg)
4、测试类
![](https://img2018.cnblogs.com/i-beta/1198522/201912/1198522-20191228130153485-213542280.jpg)
总结
通过案例的形式相信大家已经对策略模式应该有所了解了吧,其实对比的理解去学习是可以快速上手的。不过在这里呢还是要多说一句,策略模式的缺点其实也很明显,在于策略模式把每一种具体的策略都封装成一个实现类,如果策略有很多的话,很显然是实现类就会导致过多,显得臃肿。