针对问题
针对特定问题具有多种算法时,我们需要根据上下文随时切换策略,这时运用strategy模式就能良好地组织代码关系,实现灵活选择和切换。
例子
1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
3、JAVA AWT 中的 LayoutManager。
解决方法
定义一个算法的接口。每一个算法用一个类来表示,均实现这一个接口,客户端针对接口编写程序。
优点
1、算法可以自由切换。
2、避免使用多重条件判断。
3、扩展性良好。
缺点
1、策略类会增多。
2、所有策略类都需要对外暴露。
类图
实例展示
我们想要比较java读写文件策略中Channel策略、Stream策略和读写器策略三种策略的性能,就运用策略模式。首先设置一个接口,定义算法。
package iostrategy;public interface Strategyforio {/*** Read File.* * @param filename Path to file to read.* @return The result of reading.*/public String myread(String filename)throws Exception;/*** Write File.* * @param outString String to write to file.* @param filename Path to file to write.*/public void mywrite(String outString,String filename)throws Exception;
}
然后分别定义各个策略的类来实现这个接口。
Channel策略:
package iostrategy;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;public class Channel implements Strategyforio {@Overridepublic String myread(String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();StringBuilder result = new StringBuilder();try {FileInputStream f1 = new FileInputStream(filename); FileChannel fc1 = f1.getChannel();ByteBuffer b1 = ByteBuffer.allocate(1024);//初始化缓冲区大小while (fc1.read(b1) != -1) {int temp = b1.limit();b1.flip();while (temp != 0 && b1.hasRemaining()) {result.append((char)b1.get());}b1.clear();}fc1.close();f1.close();} catch (Exception e) {// TODO: handle exceptionthrow new Exception(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Channel策略读文件花费了:" + (endtime - starttime) + "ms");return result.toString();}@Overridepublic void mywrite(String outString, String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();try {FileOutputStream f1 = new FileOutputStream(filename);FileChannel fc1 = f1.getChannel();ByteBuffer buffer = ByteBuffer.wrap(outString.getBytes());fc1.write(buffer);fc1.close();f1.close();} catch (FileNotFoundException e) {// TODO 自动生成的 catch 块throw new Exception(e.toString());} catch (IOException e) {// TODO: handle exceptionthrow new Exception(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Channel策略写文件花费了:" + (endtime - starttime) + "ms");}
}
Stream策略:
package iostrategy;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class Stream implements Strategyforio {@Overridepublic String myread(String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();StringBuilder astringBuilder = new StringBuilder();try {FileInputStream f1 = new FileInputStream(filename);byte [] b = new byte[1024];int n = 0;while ((n = f1.read(b)) != -1) { // 当n不等于-1,则代表未到末尾astringBuilder.append(new String(b, 0, n));}f1.close();} catch (FileNotFoundException e) {// TODO: handle exceptionthrow new Exception(e.toString());} catch (IOException e) {// TODO: handle exceptionthrow new Exception(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Stream策略读文件花费了:" + (endtime - starttime) + "ms");return astringBuilder.toString();}@Overridepublic void mywrite(String outString, String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();try {FileOutputStream f1 = new FileOutputStream(filename);byte[] b = outString.getBytes();f1.write(b);f1.close();} catch (FileNotFoundException e) {// TODO: handle exceptionthrow new Exception(e.toString());} catch (IOException e) {// TODO: handle exceptionthrow new Exception(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Stream策略写文件花费了:" + (endtime - starttime) + "ms");}
}
读写器策略:
package iostrategy;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class WriterandReader implements Strategyforio {@Overridepublic String myread(String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();StringBuilder restfile = new StringBuilder();String temp = "";BufferedReader myRead;try {myRead = new BufferedReader(new FileReader(filename));while ((temp = myRead.readLine()) != null) {restfile.append(temp);}myRead.close();} catch (FileNotFoundException e) {// TODO 自动生成的 catch 块throw new Exception(e.toString());} catch (IOException e) {// TODO 自动生成的 catch 块throw new Exception(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Reader/Writer策略读文件花费了:" + (endtime - starttime) + "ms");return restfile.toString();}@Overridepublic void mywrite(String outString, String filename) throws Exception {// TODO 自动生成的方法存根long starttime = System.currentTimeMillis();BufferedWriter myWriter;try {myWriter = new BufferedWriter(new FileWriter(filename));myWriter.write(outString);myWriter.close();} catch (FileNotFoundException e) {// TODO 自动生成的 catch 块System.err.println(e.toString());} catch (IOException e) {// TODO 自动生成的 catch 块System.err.println(e.toString());}long endtime = System.currentTimeMillis();System.out.println("Reader/Writer策略写文件花费了:" + (endtime - starttime) + "ms");}
}
定义好一个算法接口和三个具体的策略类以后我们的策略模式就实现好了。在调用策略时我们只需要更改new的具体对象就行,如下:
Strategyforio iostrategy = new WriterandReader();
Strategyforio iostrategy = new Channel();
Strategyforio iostrategy = new Stream();