策略模式(一)
2014-06-06 22:31
106 查看
策略模式:定义一系列算法,把它们一个个封装起来,并且使他们可以相互替换.
在某些设计中,一些类的设计人员经常遇到这样的问题:由于用户需求的变化,导致经常需要修改类中的某个方法,即需要不断的改变算法.
面对这样的问题,不用担心,面向对象编程有一个很好的设计原则"面向抽象编程",该原则的核心就是将类中经常需要变化的部分分割出来,
并且把每种可能的变化对应的交给抽象类的一个子类去负责,从而让类的设计者不用去关心具体实现.
策略模式结构中包括三个角色:
策略:策略是一个接口,该接口定义了若干个算法标识,即定义了若干个抽象方法.
具体策略:具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法.
上下文:上下文是依赖于策略接口的类,即上下文中包含策略声明的变量,并且为此变量提供了set方法,最后还提供了一个方法用来委托策略变量
调用具体策略的方法.
应用场景一:在某个比赛中,有若干个评委为选手评分,请给出几种策略根据评委的评分为选手计算一个最后结果.
1.策略接口类,直接看代码:StrategyInterface.
2.具体策略类,直接看代码StrategyOne,StrategyTwo,StrategyThree.
3.上下文类,直接看代码Context.
4.最后看测试类MainTest。
应用场景二:在某个数据传输业务中,需要为文件提供几种策略用来为文件加密解密.
1.策略接口类,直接看代码:StrategyInterface.
2.具体策略类,直接看代码StrategyOne,StrategyTwo.
重点:将文件流内容转换为byte数组.:byte[] bytes = new byte[(int)fileLength],int bytesLength = bis.read(bytes)。
3.上下文类,直接看代码Context.
4.最后看测试类MainTest.
另外策略模式满足"开闭原则",即当增加新的具体策略时,不需要修改上下文类的的代码就可以引用具体策略的实例.
在某些设计中,一些类的设计人员经常遇到这样的问题:由于用户需求的变化,导致经常需要修改类中的某个方法,即需要不断的改变算法.
面对这样的问题,不用担心,面向对象编程有一个很好的设计原则"面向抽象编程",该原则的核心就是将类中经常需要变化的部分分割出来,
并且把每种可能的变化对应的交给抽象类的一个子类去负责,从而让类的设计者不用去关心具体实现.
策略模式结构中包括三个角色:
策略:策略是一个接口,该接口定义了若干个算法标识,即定义了若干个抽象方法.
具体策略:具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,即给出算法标识的具体算法.
上下文:上下文是依赖于策略接口的类,即上下文中包含策略声明的变量,并且为此变量提供了set方法,最后还提供了一个方法用来委托策略变量
调用具体策略的方法.
应用场景一:在某个比赛中,有若干个评委为选手评分,请给出几种策略根据评委的评分为选手计算一个最后结果.
1.策略接口类,直接看代码:StrategyInterface.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.one; /** * @author IluckySi * @date 20140604 */ public interface StrategyInterface { public abstract double computeScore(double[] scores); }</span>
2.具体策略类,直接看代码StrategyOne,StrategyTwo,StrategyThree.
<span style="font-size:12px;"> * @author IluckySi * @date 20140604 */ //计算代数平均值. public class StrategyOne implements StrategyInterface { @Override public double computeScore(double[] scores) { double average = 0.0; double sum = 0.0; for(int i = 0; scores != null && i < scores.length; i++) { sum += scores[i]; } average = sum / scores.length; return average; } }</span>
<span style="font-size:12px;">package com.ilucky.pattern.strategy.one; import java.util.Arrays; /** * @author IluckySi * @date 20140604 */ //计算几何平均值. public class StrategyTwo implements StrategyInterface { @Override public double computeScore(double[] scores) { double average = 0.0; double sum = 1.0; Arrays.sort(scores); for(int i = 0; i < scores.length; i++) { sum *= scores[i]; } average = Math.pow(sum, 1.0 / scores.length); return average; } } </span>
<span style="font-size:12px;">package com.ilucky.pattern.strategy.one; import java.util.Arrays; /** * @author IluckySi * @date 20140604 */ //计算去掉一个最高分和最低分代数平均值. public class StrategyThree implements StrategyInterface { @Override public double computeScore(double[] scores) { double average = 0.0; double sum = 0.0; Arrays.sort(scores); for(int i = 1; i < scores.length - 1; i++) { sum += scores[i]; } average = sum / (scores.length - 2); return average; } }</span>
3.上下文类,直接看代码Context.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.one; /** * @author IluckySi * @date 20140604 */ public class Context { private StrategyInterface strategyInterface; public void setStrategyInterface(StrategyInterface strategyInterface) { this.strategyInterface = strategyInterface; } public double computeScore(double[] scores) { return strategyInterface.computeScore(scores); } }</span>
4.最后看测试类MainTest。
<span style="font-size:12px;">package com.ilucky.pattern.strategy.one; /** * @author IluckySi * @date 20140604 */ public class MainTest { public static void main(String[] args) { //模拟评分. double[] scores = new double[6]; scores[0] = 50; scores[1] = 68; scores[2] = 72; scores[3] = 85; scores[4] = 90; scores[5] = 96; //创建上下文. Context context = new Context(); //计算代数平均值. StrategyInterface strategyOne = new StrategyOne(); context.setStrategyInterface(strategyOne); double resultOne = context.computeScore(scores); System.out.println("代数平均值:" + resultOne); //计算几何平均值. StrategyInterface strategyTwo = new StrategyTwo(); context.setStrategyInterface(strategyTwo); double resultTwo = context.computeScore(scores); System.out.println("几何平均值:" + resultTwo); //计算去掉一个最高分和最低分代数平均值. StrategyInterface strategyThredd = new StrategyThree(); context.setStrategyInterface(strategyThredd); double resultThreee = context.computeScore(scores); System.out.println("去掉一个最高分和最低分代数平均值:" + resultThreee); } } /** 运行结果: 代数平均值:76.83333333333333 几何平均值:75.12607167549113 去掉一个最高分和最低分代数平均值:78.75 */</span>
应用场景二:在某个数据传输业务中,需要为文件提供几种策略用来为文件加密解密.
1.策略接口类,直接看代码:StrategyInterface.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.two; import java.io.File; /** * @author IluckySi * @date 20140605 */ public interface StrategyInterface { public abstract void encrypt(File file); public abstract void decrypt(File file); }</span>
2.具体策略类,直接看代码StrategyOne,StrategyTwo.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.two; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; /** * @author IluckySi * @date 20140605 */ public class StrategyOne implements StrategyInterface { private String password; public StrategyOne() { this.password = "IluckySi"; } public StrategyOne(String password) { this.password = password; } /** * 使用一个字符串做密码,比如用IluckySi做密码,首先将IluckySi转换为一个字节数组,然后获取bytes数组的长度length, * 最后将文件的内容按顺序以length个字节为一组,对每一组中的字节和bytes字节数组中对应的字节做加法运算. */ @Override public void encrypt(File file) { byte[] passwordBytes = password.getBytes(); FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { //对文件内容加密. fis = new FileInputStream(file); bis = new BufferedInputStream(fis); long fileLength = file.length(); byte[] bytes = new byte[(int)fileLength]; //重点:将文件流内容转换为byte数组. int bytesLength = bis.read(bytes); for(int i = 0; i < bytesLength; i++) { int encrpyt = bytes[i] + passwordBytes[i % passwordBytes.length]; bytes[i] = (byte)encrpyt; } //对文件内容加完密再写回文件. fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); fos.write(bytes, 0 , bytesLength); System.out.println("文件" + file.getPath() + "已经成功完成加密!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if(bos != null) { bos.close(); bos = null; } if(fos != null) { fos.close(); fos = null; } if(bis != null) { bis.close(); bis = null; } if(fis != null) { fis.close(); fis = null; } } catch (Exception e) { e.printStackTrace(); } } } /** * 将文件按密码的长度分组, 然后和密码对应的字节数组做减法运算. */ @Override public void decrypt(File file) { byte[] passwordBytes = password.getBytes(); FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { //对文件内容解密. fis = new FileInputStream(file); bis = new BufferedInputStream(fis); long fileLength = file.length(); byte[] bytes = new byte[(int)fileLength]; //重点:将文件流内容转换为byte数组. int bytesLength = bis.read(bytes); for(int i = 0; i < bytesLength; i++) { int encrpyt = bytes[i] - passwordBytes[i % passwordBytes.length]; bytes[i] = (byte)encrpyt; } //对文件内容解完密再写回文件. fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); fos.write(bytes); System.out.println("文件" + file.getPath() + "已经成功完成解密!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if(bos != null) { bos.close(); bos = null; } if(fos != null) { fos.close(); fos = null; } if(bis != null) { bis.close(); bis = null; } if(fis != null) { fis.close(); fis = null; } } catch (Exception e) { e.printStackTrace(); } } } } </span>
<span style="font-size:12px;">package com.ilucky.pattern.strategy.two; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; /** * @author IluckySi * @date 20140606 */ public class StrategyTwo implements StrategyInterface { private String password; public StrategyTwo() { this.password = "IluckySi"; } public StrategyTwo(String password) { this.password = password; } /** * 使用一个字符串做密码,比如用IluckySi做密码,首先将IluckySi转换为一个字节数组,然后获取bytes数组的长度length, * 最后将文件的内容按顺序以length个字节为一组,对每一组中的字节和bytes字节数组中对应的字节做异或运算. */ @Override public void encrypt(File file) { byte[] passwordBytes = password.getBytes(); FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { //对文件内容加密. fis = new FileInputStream(file); bis = new BufferedInputStream(fis); long fileLength = file.length(); byte[] bytes = new byte[(int)fileLength]; //重点:将文件流内容转换为byte数组. int bytesLength = bis.read(bytes); for(int i = 0; i < bytesLength; i++) { int encrpyt = bytes[i] ^ passwordBytes[i % passwordBytes.length]; bytes[i] = (byte)encrpyt; } //对文件内容加完密再写回文件. fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); fos.write(bytes, 0 , bytesLength); System.out.println("文件" + file.getPath() + "已经成功完成加密!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if(bos != null) { bos.close(); bos = null; } if(fos != null) { fos.close(); fos = null; } if(bis != null) { bis.close(); bis = null; } if(fis != null) { fis.close(); fis = null; } } catch (Exception e) { e.printStackTrace(); } } } /** * 将文件按密码的长度分组, 然后和密码对应的字节数组做异或运算. */ @Override public void decrypt(File file) { byte[] passwordBytes = password.getBytes(); FileInputStream fis = null; BufferedInputStream bis = null; FileOutputStream fos = null; BufferedOutputStream bos = null; try { //对文件内容解密. fis = new FileInputStream(file); bis = new BufferedInputStream(fis); long fileLength = file.length(); byte[] bytes = new byte[(int)fileLength]; //重点:将文件流内容转换为byte数组. int bytesLength = bis.read(bytes); for(int i = 0; i < bytesLength; i++) { int encrpyt = bytes[i] ^ passwordBytes[i % passwordBytes.length]; bytes[i] = (byte)encrpyt; } //对文件内容解完密再写回文件. fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos); fos.write(bytes); System.out.println("文件" + file.getPath() + "已经成功完成解密!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if(bos != null) { bos.close(); bos = null; } if(fos != null) { fos.close(); fos = null; } if(bis != null) { bis.close(); bis = null; } if(fis != null) { fis.close(); fis = null; } } catch (Exception e) { e.printStackTrace(); } } } }</span>
重点:将文件流内容转换为byte数组.:byte[] bytes = new byte[(int)fileLength],int bytesLength = bis.read(bytes)。
3.上下文类,直接看代码Context.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.two; import java.io.File; /** * @author IluckySi * @date 20140605 */ public class Context { private StrategyInterface strategyInterface; public void setStrategyInterface(StrategyInterface strategyInterface) { this.strategyInterface = strategyInterface; } public void encrypt(File file) { strategyInterface.encrypt(file); } public void decrypt(File file) { strategyInterface.decrypt(file); } }</span>
4.最后看测试类MainTest.
<span style="font-size:12px;">package com.ilucky.pattern.strategy.two; import java.io.File; /** * @author IluckySi * @date 20140605 */ public class MainTest { public static void main(String[] args) { //测试文件. File one = new File("E:/one.txt"); File two = new File("E:/two.txt"); //创建上下文. Context context = new Context(); //通过第一种策略加密解密. StrategyInterface strategyOne = new StrategyOne(); context.setStrategyInterface(strategyOne); context.encrypt(one); context.decrypt(one); //通过第二种策略加密解密. StrategyInterface strategyTwo = new StrategyTwo(); context.setStrategyInterface(strategyTwo); context.encrypt(two); context.decrypt(two); } } </span>策略模式的优点:上下文和具体策略是松耦合关系,即上下文中包含一个策略变量,但不需要知道具体的策略是什么.
另外策略模式满足"开闭原则",即当增加新的具体策略时,不需要修改上下文类的的代码就可以引用具体策略的实例.
相关文章推荐
- 设计模式之Strategy(策略)
- 设计模式(20)-策略模式(Strategy)
- 策略模式之C++版本
- 应用泛型的策略模式
- 对象模型--策略、模式、应用 笔记1
- [浪子学编程][MS Enterprise Library]ObjectBuilder之设计模式(一):策略模式
- (22)策略模式-Strategy Pattern-康熙收复台湾-明珠和索额图的不同策略
- 从诸葛亮的三个锦囊妙计谈策略模式
- 《Java与模式》学习笔记之九-----策略模式(Strategy Pattern)
- AspectJ实现设计模式(二)——策略模式
- 设计模式之Strategy(策略)
- 设计模式之Strategy(策略)
- 策略模式之C#版本(原创翻译版本)
- 设计模式实战(一)——使用策略模式(strategy pattern)实现多关键字排序
- Delphi模式编程之策略模式(下)
- 設計模式之Strategy(策略)
- 深入浅出策略模式
- 设计模式——策略模式
- 设计模式之策略模式(Strategy)
- 对象模型--策略、模式、应用 笔记2---选择对象