欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Strategy策略

程序员文章站 2022-07-13 17:16:12
...

针对问题

针对特定问题具有多种算法时,我们需要根据上下文随时切换策略,这时运用strategy模式就能良好地组织代码关系,实现灵活选择和切换。

例子

1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
3、JAVA AWT 中的 LayoutManager。

解决方法

定义一个算法的接口。每一个算法用一个类来表示,均实现这一个接口,客户端针对接口编写程序。

优点

1、算法可以*切换。
2、避免使用多重条件判断。
3、扩展性良好。

缺点

1、策略类会增多。
2、所有策略类都需要对外暴露。

类图

Strategy策略

实例展示

我们想要比较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 {

  @Override
  public 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 exception
      throw new Exception(e.toString());
    }
    long endtime = System.currentTimeMillis();
    System.out.println("Channel策略读文件花费了:" + (endtime - starttime) + "ms");
    return result.toString();
  }

  @Override
  public 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 exception
      throw 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 {

  @Override
  public 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 exception
      throw new Exception(e.toString());
    } catch (IOException e) {
      // TODO: handle exception
      throw new Exception(e.toString());
    }
    long endtime = System.currentTimeMillis();
    System.out.println("Stream策略读文件花费了:" + (endtime - starttime) + "ms");
    return astringBuilder.toString();
  }

  @Override
  public 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 exception
      throw new Exception(e.toString());
    } catch (IOException e) {
      // TODO: handle exception
      throw 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 {

  @Override
  public 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();
  }

  @Override
  public 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();