策略,古时也称“计”,指为了达成某个目标而提前策划好的方案。但计划往往不如变化快,当目标突变或者周遭情况不允许实施某方案的时候,我们就得临时变更方案。策略模式(Strategy)强调的是行为的灵活切换,比如一个类的多个方法有着类似的行为接口,可以将它们抽离出来作为一系列策略类,在运行时灵活对接,变更其算法策略,以适应不同的场景。
提示:以下是本篇文章正文内容,下面案例可供参考
一个设计优秀的系统,绝不能来回更改底层代码,而是要站在高层抽象的角度构筑一套相对固化的模式,并能使新加入的代码以实现类的方式接入系统,让系统功能得到无限的算法扩展,以适应用户需求的多样性。
我们先从一个反例开始,了解一个有设计缺陷的系统。流行于20世纪80年代的便携式掌上游戏机的系统设计非常简单,最常见的是“俄罗斯方块”游戏机。这种游戏机只能玩一款游戏,所以玩家逐渐减少,最终退出了市场。这是一种嵌入式系统设计,主机不包含任何操作系统。制造商只是简单地将软件固化在游戏机芯片中,造成游戏(软件)与游戏机(硬件)的强耦合。玩家要想换个游戏就得再购买一台游戏机,严重缺乏可扩展性。
这种耦合性极高的系统设计类似的还有计算器,它只能用于简单的数学运算,算法功能到此为止,没有后续扩展的可能性。我们就以计算器为例,探讨一下这种设计存在的问题。假设计算器可以进行加减法运算。
public class Calculator {public int add(int a, int b) {//加法return a + b;}public int sub(int a, int b) {//减法return a + b;}
}
注意:
通过分析和对比代码清中的计算器类,我们不难发现,不管是何种算法(加、减、乘、除等),都属于运算。从外部来看,它们都是基于对两个数字型入参的运算接口,并能返回数字型的运算结果。既然如此,不如把这些算法抽离出来,使它们独立于计算器,并各自封装,让一种算法对应一个类,要使用哪种算法时将其接入即可,如此算法扩展便得到了保证。这种设计上的演变不正类似于从嵌入式掌上游戏机到可插卡式游戏机的演变吗?
策略与系统分离的设计看起来非常灵活,基于这种设计思想,我们对计算器类进行重构。首先要对一系列的算法进行接口抽象,也就是为所有的算法(加法、减法或者即将加入的其他算法)定义一个统一的算法策略接口
public interface Strategy {public int calculate(int a,int b);//操作数a,被操作数b
}
要点:
//加法策略类
public class Addition implements Strategy{@Overridepublic int calculate(int a, int b) {return a + b;}
}
//减法策略类
public class Subtraction implements Strategy{@Overridepublic int calculate(int a, int b) {return a - b;}
}
要点:
public class Calculator {private Strategy strategy;//算法策略接口public void setStrategy(Strategy strategy) {this.strategy = strategy;}public int getResult(int a, int b){return this.strategy.calculate(a, b);//返回具体策略的运算结果}
}
要点:
public class Client {public static void main(String[] args) {Calculator calculator = new Calculator();//实例化计算器calculator.setStrategy(new Addition());//注入加法策略实现System.out.println(calculator.getResult(1,1));//输出结果为2calculator.setStrategy(new Subtraction());//再注入减法策略实现System.out.println(calculator.getResult(1, 1));//输出结果为0}
}
说明:
相信计算机、USB接口还有各种设备之间的关系以及使用方法都非常熟悉了,这些模块组成的系统正是策略模式的最佳范例
与之前的计算器实例类似,首先我们定义策略接口。
public interface USB {public void read();
}
//键盘
public class KeyBoard implements USB{@Overridepublic void read() {System.out.println("键盘指令数据......");}
}
//鼠标
public class Mouse implements USB{@Overridepublic void read() {System.out.println("鼠标指令数据......");}
}
//摄像头
public class Camera implements USB{@Overridepublic void read() {System.out.println("视频流指令数据......");}
}
说明:
public class Computer {private USB usb;//主机上的USB接口public void setUsb(USB usb) {this.usb = usb;}public void compute(){usb.read();}
}
public class Client {public static void main(String[] args) {Computer com = new Computer();com.setUsb(new KeyBoard());//插入键盘com.compute();com.setUsb(new Mouse());//插入鼠标com.compute();com.setUsb(new Camera());//插入摄像头com.compute();}
}
输出结果:
键盘指令数据......
鼠标指令数据......
视频流指令数据......
说明:
提示:这里对文章进行总结:
策略模式让策略与系统环境彻底解耦,通过对算法策略的抽象、拆分,再拼装、接入外设,使系统行为的可塑性得到了增强。策略接口的引入也让各种策略实现彻底解放,最终实现算法分立,即插即用。
策略模式的各角色定义如下:
上一篇:Axure绘制登录功能
下一篇:C++4:C++中的动态内存管理