什么是策略模式
首先策略模式属于GOF23中设计模式中的一种,是一种行为型的设计模式。“行为”主要是指不同的方法或者算法。
其实就是我们定义和封装一些策略(或者说是算法),这些策略是可以相互替换的。然后客户端类通过使用这些不同的策略就可以表现出不同的行为。
相信大家一定见到过if-else 满天飞的代码,其实可以考虑使用策略模型进行优化。
策略模式代码示例
这里我们以上班需要选择不同的交通工具为例,说明策略模式的实现。
1、首先建立一个接口,这个接口是所有策略类都要实现的,这样才能保证是可以相互替换的。即创建一个TrafficWayStrategy接口:
public interface TrafficWayStrategy {void toWorkBy();}
2、然后创建三种不同的实现方式,也就是不同的策略:
public class BikeStrategy implements TrafficWayStrategy{public void toWorkBy() {System.out.println("骑自行车去上班");}}public class BusStrategy implements TrafficWayStrategy{public void toWorkBy() {System.out.println("坐公交去上班");}}public class DidiStrategy implements TrafficWayStrategy{public void toWorkBy() {System.out.println("打滴滴去上班");}}
3、创建策略模式context类,使用策略实现行为。在该类中持有策略对象的引用,注意是接口类型的引用,这样才能使用多态特性实现策略的切换:
public class WorkTo {private TrafficWayStrategy strategy;public WorkTo(TrafficWayStrategy strategy) {this.strategy = strategy;}// 改变策略的方法public void chageStrategy(TrafficWayStrategy strategy){this.strategy = strategy;}public void toWork(){System.out.println("小明同学");strategy.toWorkBy();}}
至此,策略模式的代码已经完毕。新建测试类或客户端调用陈旭,验证:
public class StratetyMain {public static void main(String[] args) {TrafficWayStrategy strategy = new BikeStrategy();WorkTo workTo = new WorkTo(strategy);workTo.toWork();// 小明不想骑自行车上班了,要打滴滴workTo.chageStrategy(new DidiStrategy());workTo.toWork();}}
看下运行结果:
小明同学骑自行车去上班小明同学打滴滴去上班
策略模式使用场景
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。
3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
策略模式在源码中应用
1、集合工具类Collections中的sort方法,其中有一个参数是Comparator类型的对象。这里Comparator接口就是抽象策略,我们可以自己实现其中的compare()方法,代表不同的实现策略。
public static <T> void sort(List<T> list, Comparator<? super T> c) {list.sort(c);}
2、我们之前讨论过线程池的7个核心参数(不了解的可以看下这篇Java并发编程一万字总结(吐血整理)-续篇),其中最后一个参数就是拒绝策略RejectedExecutionHandler。在线程池使用静态内部类的方式实现了四种策略:
AbortPolicy:直接抛出异常。CallerRunsPolicy:只用调用者所在线程来运行任务。DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。DiscardPolicy:不处理,丢弃掉。
这里使用的就是典型的策略模式的一种实现了。
3、再有我们IO流中的File文件类,其中有一个list()方法,用于列出所有文件名,该方法可以传入一个FilenameFilter类型的参数,FilenameFilter是一个接口。我们可以自己实现过滤策略。
public String[] list(FilenameFilter filter) {String names[] = list();if ((names == null) || (filter == null)) {return names;}List<String> v = new ArrayList<>();for (int i = 0 ; i < names.length ; i++) {if (filter.accept(this, names[i])) {v.add(names[i]);}}return v.toArray(new String[v.size()]);}
FilenameFilter 是个接口,可以理解我抽象策略接口
public interface FilenameFilter {boolean accept(File dir, String name);}
设计模式系列文章回顾
Java面试必备:手写单例模式
工厂模式超详解(代码示例)
设计模式之原型模式
设计模式之代理模式
设计模式之委派模式,大名鼎鼎的Spring都在用
我要打十个!详解建造者模式(builder pattern)