策略模式的结构中包含3种角色:策略(Strategy)、上下文(Context
、具体策略(ConcreteStrategy)
策略模式具有以下优点:
1.上下文(Context)和具体策略(ConcreteStrategy)是松耦合关系
因此上下文只知道它要使用Strategy接口类的实例,但不需要知道
具体是哪一个类。
2.策略模式满足“开-闭”原则。当增加新的具体原则时,
不需要修改上下文类的代码,上下文就可以引用新的具体策略的实例。
适合使用策略模式的情景:
1.一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件
语句的形式出现,那么可以使用策略模式避免在类中使用大量的条件语
句。
2.程序的主要类(相当于上下文的角色)不希望暴露复杂的、
与算法相关的数据结构,那么可以使用策略模式封装算法,
即算法分别封装到具体策略中。
3.需要使用一个算法的不同变体。
例一:
策略接口:
public interface Strategy {
public double computerAverage(double a[]);
}
实现策略接口的具体策略A:
public class ConcreteStrategyA implements Strategy{
@Override
public double computerAverage(double a[]) {
double sum = 0, score = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
score = sum / a.length;
return score;
}
}
实现策略接口的具体策略B:
public class ConcreteStrategyB implements Strategy{
@Override
public double computerAverage(double a[]) {
if (a.length <= 2)
return 0;
double sum = 0, score = 0;
for (int i = 1; i < a.length-1; i++) {
sum += a[i];
}
score = sum / (a.length - 2);
return score;
}
}
人:
class Person {
String name;
double score;
public void setScore(double t) {
score = t;
}
public void setName(String s) {
name = s;
}
public double getScore() {
return score;
}
public String getName() {
return name;
}
}
选择策略:
public class AverageScore {
Strategy strategy;
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public double getAverage(double a[]) {
if(strategy != null) {
return strategy.computerAverage(a);
} else {
System.out.println("没有求平均值的方法,得到的-1不代表平均值");
return -1;
}
}
}
Main主类:
public class Main {
public static void main(String[] args) {
AverageScore game = new AverageScore();
game.setStrategy(new ConcreteStrategyA());
Person wang = new Person();
wang.setName("王建");
double [] a = {9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.0};
double aver = game.getAverage(a);
wang.setScore(aver);
System.out.println("算法A:");
System.out.printf("%s的最后得分是%5.3f%n", wang.getName(), wang.getScore());
game.setStrategy(new ConcreteStrategyB());
aver = game.getAverage(a);
wang.setScore(aver);
System.out.println("算法B:");
System.out.printf("%s的最后得分是%5.3f", wang.getName(), wang.getScore());
}
}
例二:
策略接口:
import java.io.File;
public interface EncryptStrategy {
public void setPassword(String s);
public abstract void encryptFile(File file);
public abstract String decryptFile(File file);
}
实现策略接口的具体策略一:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class StrategyOne implements EncryptStrategy{
String password;
@Override
public void setPassword(String s) {
password = s;
}
@Override
public void encryptFile(File file) {
try {
File tempFile = new File("C:\\Users\\Administrator\\Desktop\\temp.txt");
byte [] secret = password.getBytes();
FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(tempFile);
int n = secret.length, m = -1;
byte [] content = new byte[n];
while((m = in.read(content, 0, n)) != -1) {
for (int k = 0; k < m; k++) {
content[k] = (byte)(content[k] + secret[k]);//加密
}
out.write(content, 0, m);//将加密写入临时文件
}
in.close();
out.close();
in = new FileInputStream(tempFile);
out = new FileOutputStream(file);
byte [] c = new byte[10];
while ((m = in.read(c, 0, 10))!= -1) {
out.write(c, 0, m); //加密文件替换原来的文件
}
tempFile.delete();
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String decryptFile(File file) {
try {
byte [] a = password.getBytes();
long length = file.length();
FileInputStream in = new FileInputStream(file);
byte [] c = new byte[(int) length];
int m = in.read(c);
for (int k = 0; k < m; k++) {
int n = c[k] - a[k%a.length];
c[k] = (byte)n;
}
in.close();
return new String(c);
} catch (Exception e) {
return e.toString();
}
}
}
实现策略接口的具体策略二:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class StrategyTwo implements EncryptStrategy {
String password;
@Override
public void setPassword(String s) {
password = s;
}
@Override
public void encryptFile(File file) {
try {
File tempFile = new File("C:\\Users\\Administrator\\Desktop\\temp.txt");
byte[] secret = password.getBytes();
FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(tempFile);
int n = secret.length, m = -1;
byte[] content = new byte[n];
while ((m = in.read(content, 0, n)) != -1) {
for (int k = 0; k < m; k++) {
content[k] = (byte) (content[k] ^ secret[k]);// 加密
}
out.write(content, 0, m);// 将加密写入临时文件
}
in.close();
out.close();
in = new FileInputStream(tempFile);
out = new FileOutputStream(file);
byte[] c = new byte[10];
while ((m = in.read(c, 0, 10)) != -1) {
out.write(c, 0, m); // 加密文件替换原来的文件
}
tempFile.delete();
in.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public String decryptFile(File file) {
try {
byte [] a = password.getBytes();
long length = file.length();
FileInputStream in = new FileInputStream(file);
byte [] c = new byte[(int) length];
int m = in.read(c);
for (int k = 0; k < m; k++) {
int n = c[k] ^ a[k%a.length];
c[k] = (byte)n; //解密
}
in.close();
return new String(c);
} catch (Exception e) {
return e.toString();
}
}
}
选择策略:
import java.io.File;
public class EncodeContext {
EncryptStrategy strategy;
public void setStrategy(EncryptStrategy strategy) {
this.strategy = strategy;
}
public void encryptFile(File file) {
if (strategy != null) {
strategy.encryptFile(file);
} else {
System.out.println("没有加密策略可用!!");
}
}
public String decryptFile(File file) {
if (strategy != null) {
return strategy.decryptFile(file);
} else {
return "";
}
}
}
Main主类:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
public class Main {
public static void main(String[] args) {
File fileOne = new File("C:\\Users\\Administrator\\Desktop\\A.txt");
File fileTwo = new File("C:\\Users\\Administrator\\Desktop\\B.txt");
EncodeContext encode = new EncodeContext(); //上下文对象
EncryptStrategy one = new StrategyOne();
String password = "xuzifeng";
one.setPassword(password);
encode.setStrategy(one); //上下文对象使用策略一
encode.encryptFile(fileOne);
System.out.println(fileOne.getName() + "加密后的内容:");
String s = "";
try {
FileReader inOne = new FileReader(fileOne);
BufferedReader inTwo = new BufferedReader(inOne);
while((s = inTwo.readLine()) != null) {
System.out.println(s);
}
inOne.close();
inTwo.close();
} catch (Exception e) {
e.printStackTrace();
}
String str = encode.decryptFile(fileOne);
System.out.println(fileOne.getName() + "解密后的内容:");
System.out.println(str);
EncryptStrategy two = new StrategyTwo();
password = "wangjian";
two.setPassword(password);
encode.setStrategy(two); //上下文对象使用策略二
encode.encryptFile(fileTwo);
System.out.println(fileTwo.getName() + "加密后的内容:");
try {
FileReader inOne = new FileReader(fileTwo);
BufferedReader inTwo = new BufferedReader(inOne);
while((s = inTwo.readLine()) != null) {
System.out.println(s);
}
inOne.close();
inTwo.close();
} catch (Exception e) {
e.printStackTrace();
}
str = encode.decryptFile(fileTwo);
System.out.println(fileTwo.getName() + "解密后的内容:");
System.out.println(str);
}
}
参考:https://www.cnblogs.com/dotgua/p/strategy-pattern.html
https://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html