什么是策略模式?
个人认为,设计模式的定义是比较晦涩抽象的,了解设计模式的最合适的方法就是先看看它的使用场景和相关案例,Java的JDK中就有此设计模式的体现。先讲一个比较简单的,那就是File的文件过滤机制。File类中有个list(FilenameFilter filter)的方法用于过滤File对象(如果是目录的话)下文件及文件夹。
list方法 (File.java 部分代码),其中无参的list方法是获取目录下所有文件及文件夹的名称。
注:File类并不保留策略,每次过滤都需传入策略类。在其他策略模式的案例中,可能会保留本次策略引用。
FilenameFilter接口,在其实现类中,根据文件的相关参数对是否通过过滤进行判断。
JDK并没有提供FileFilter的实现类,而是让编程者根据需要自由发挥。如下所示,可以编程者可以根据正则表达式对文件进行过滤。
以上例子,"策略"指的就是文件的过滤方案(或者说,是算法)。它的思想就是可以根据需要,灵活的创建并替换策略(这里指过滤方案),而不影响客户端(这里指File对象)。
在增加策略时,策略模式是如何防止对客户端(策略执行者)的修改的?
这里有必要提一下策略模式体现的OO原则:
(1)封装变化:在File类中,过滤方式就是变化点,在实际需求中可能经常发生变化,这样的话,过滤方式就不能写死在File类中(如果这样的话,要更换过滤方式,只能通过子类覆盖的方法实现),而是从File类中抽取出来,封装成另一个策略类,然后由File类引用。这样,File类就只管引用策略类并调用即可。
(2)针对接口编程,而不是针对实现编程:如上,list方法中只根据FilenameFilter接口进行编程,调用接口方法。不会涉及到具体类的其他方法,所以,不管具体类是什么,list方法调用过程都无需改变。
策略模式在JDK中还有那些使用案例?
策略模式在JDK线程池中也有使用。这里,简要地提一下。在固定大小的线程池实现中,有这样一种情况,即当前线程池内的所有线程都在使用状态,而此时又有新的任务进来,这时候如何处理这个新任务就有多种方案了。有的直接拒绝,有的拒绝但会抛出异常,有的阻塞直到有可用的线程,有的移除一个任务来执行当前任务,有的用当前线程执行任务。这几种方案,并没有明确的优劣之分。可以根据应用场景进行选择。