介绍
在开发中也经常遇到这种情况,实现某一个功能往往有许多算法或者策略,我们在实际开发中选择不同的算法或策略来完成该功能。一般的情况是我们会把所有的算法或策略写入一个类中,通过if…else…或case语句来根据实际情况来选择具体算法或策略,但是这种方法会使这个类臃肿,维护难,当增加一种算法或策略时又要修改源代码,违反了面向对象的单一原则和开闭原则。如果将这些算法或者策略抽象出来,提供一个统一的接口,不同的算法或策略有不同的实现类,在实际使用时通过动态注入来实现算法或策略的替换,这种模式扩展性高,维护性好,也就是本次所说的策略模式。
定义
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们相互可以替换。让算法独立于客户端变化。
使用场景
(1)需要安全的封装多种同一类型的操作时
(2)出现同一抽象类有多个子类,而又需要使用if..else..或case语句来选择具体子类时
类图
角色介绍:
- Context - 用来操作策略的上下文环境
- Stragety - 策略的抽象
- ConcreteStragetyA、B - 具体的策略实现
简单实现
我们在写代码时经常会遇到对一个数组排序,排序的算法有很多比如插入排序,归并排序,冒泡排序等,我们在实际开发中要选择一种算法来对数组排序,一般情况下我们会这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class Client {
private static final int INSERT_SORT = 0; private static final int MERGE_SORT = 1; private static final int BUBBLE_SORT = 2;
public static void main(String[] args){ Client client = new Client(); int[] a = new int[]{1, 2, 3, 4, 5, 6}; client.show(a, INSERT_SORT); }
private void show(int[] a, int type){ if(type == INSERT_SORT){ insetSort(a); }else if (type == MERGE_SORT){ mergeSort(a); }else if (type == BUBBLE_SORT){ bubbleSort(a); } for(int b : a){ System.out.print(b + " "); } }
private void insetSort(int[] a){ }
private void mergeSort(int[] a){ }
private void bubbleSort(int[] a){ } }
|
这里并不是讨论算法,就没有给出算法的具体实现,上面我们使用type类型通过if…else…语句来动态决定使用哪一种排序算法,当我们增加一种算法时,就要在函数中增加一个判断,以此类推,这样会使代码变得臃肿,一改很多处都要改。下面用策略模式进行重构,首先定义一个抽象的排序接口。
抽象的排序接口,即抽象策略角色
1 2 3
| public interface Sort{ <T> void sort(T[] a); }
|
具体策略实现类
1 2 3 4 5 6
| public class BubbleSort implements Sort { @Override public <T> void sort(T[] a) { } }
|
1 2 3 4 5 6 7
| public class InsertSort implements Sort{
@Override public <T> void sort(T[] a) { } }
|
1 2 3 4 5 6 7
| public class MergeSort implements Sort {
@Override public <T> void sort(T[] a) { } }
|
客户端,用来操作策略的上下文环境,即Context角色。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public class Client {
private Sort mSort;
public static void main(String[] args){ Client client = new Client(); Sort bubbleSort = new BubbleSort(); client.setmSort(bubbleSort); Integer[] a = {1, 2, 3, 4, 5, 6}; client.show(a); }
public void setmSort(Sort mSort) { this.mSort = mSort; }
public void show(Integer[] a){ mSort.sort(a); for(Integer b : a){ System.out.print(b + " "); } }
}
|
通过上述实例可以清晰的看出两者的区别,前面说通过if..else语句来解决问题,而后者是通过建立抽象,将不同的算法构建成一个个具体的策略实现,通过不同的策略注入实现算法替换。
结语
策略模式主要用来分离算法,在简化逻辑结构的同时,增强了系统的可读性,稳定性,可扩展性,这对于复杂的业务逻辑显得更为直观,通过建立抽象,注入不同实现,从而达到很好的扩展性。
本文源码相关位置
最終更新:
谢谢大家的阅读!