定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换,本模式使得算法可以独立于使用它的客户而变化。策略模式包括以下三种角色

  • 策略(Strategy):策略是一个接口,该接口定义若干个算法标识,定义了若干个抽象方法。
  • 具体策略(ConcreteStrategy):具体策略是实现策略接口的类,具体策略实现策略接口所定义的抽象方法,给出算法标识的具体算法。
  • 上下文(Context):上下文是依赖策略接口的类,即上下文包含有策略声明的变量。上下文中提供一个方法,该方法委托策略变量调用具体策略所实现的策略接口中方法。

  策略模式的UML类图如下图所示:

策略模式的优点:

  上下文和具体策略是松耦合的关系,上下文只知道它要使用某一个实现Strategy接口类的实例,但不需要知道具体是哪一类。

  策略模式满足“开-闭原则”。当增加新的具体策略时,不需要修改上下文类的代码,上下文就可以引用新的具体策略实例。

策略模式的使用场景:

  一个类定义了多种行为,并且这些行为在这个类的方法中以多个条件语句的形式出现,那么可以使用策略模式避免在类中使用大量的条件语句。

  程序不希望暴露复杂的。与算法相关的数据结构,可以使用策略模式封装算法。

  需要使用一个算法的不同实体。

应用举例 —— 加密、解密文件

  用户需要对已有的文件进行加密处理,请提供几种加密方案。

 设计实现可以使用策略模式,具体如下:

  1. 策略接口的名称是EncryptStrategy,该接口有两个抽象方法,一个是加密,一个是解密

public interface EncryptStrategy {
public abstract void encryptFile(File file);
public abstract void decryptFile(File file);
}

  2. 具体策略,有两个具体策略,StrategyONE和StrategyTWO

    • StrategyONE使用一个字符串做密码,比如password,将这个字符串编码到一个字节数组,byte[] e = password.getBytes(); 假设e的长度是n,那么就将文件内容以n字节为一组,对每组中字节,用数组e对应字节做加法运算,解密的话就是相应的做减法运算。
    • StrategyTWO使用一个字符串做密码,比如password,将这个字符串编码到一个字节数组,byte[] e = password.getBytes(); 假设e的长度是n,那么就将文件内容按顺序以n字节为一组对每组中字节,使用数组e的对应字节做异或运算
public class StrategyOne implements EncryptStrategy {
String password; public StrategyOne(String password) {
if(password == null||password.trim().length()==0)
this.password = "I love java";
this.password = password;
}
public StrategyOne() {
this.password = "I love java";
}
public void encryptFile(File file) {
try {
byte[] a = this.password.getBytes();
FileInputStream fis = new FileInputStream(file);
long length = file.length();
byte[] c = new byte[(int)length];
int m = fis.read();
for (int i = 0; i < m; i++) {
int n = c[i]+a[i%a.length];
c[i] = (byte) n;
}
fis.close();
FileOutputStream fos = new FileOutputStream(file);
fos.write(c, 0, m);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} public void decryptFile(File file) {
try {
byte[] a = this.password.getBytes();
FileInputStream fis = new FileInputStream(file);
long length = file.length();
byte[] c = new byte[(int)length];
int m = fis.read();
for (int i = 0; i < m; i++) {
int n = c[i]-a[i%a.length];
c[i] = (byte) n;
}
fis.close();
FileOutputStream fos = new FileOutputStream(file);
fos.write(c, 0, m);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
public class StrategyTWO implements EncryptStrategy {
String password; public StrategyTWO(String password) {
if(password == null||password.trim().length()==0)
this.password = "I love java";
this.password = password;
}
public StrategyTWO() {
this.password = "I love java";
}
@Override
public void encryptFile(File file) {
try {
byte[] a = this.password.getBytes();
FileInputStream fis = new FileInputStream(file);
long length = file.length();
byte[] c = new byte[(int)length];
int m = fis.read();
for (int i = 0; i < m; i++) {
int n = c[i]^a[i%a.length];
c[i] = (byte) n;
}
fis.close();
FileOutputStream fos = new FileOutputStream(file);
fos.write(c, 0, m);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void decryptFile(File file) {
try {
byte[] a = this.password.getBytes();
FileInputStream fis = new FileInputStream(file);
long length = file.length();
byte[] c = new byte[(int)length];
int m = fis.read();
for (int i = 0; i < m; i++) {
int n = c[i]^a[i%a.length];
c[i] = (byte) n;
}
fis.close();
FileOutputStream fos = new FileOutputStream(file);
fos.write(c, 0, m);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

  3. 上下文,该类包含策略声明用于保存具体策略的引用变量,代码如下

public class EncodeContext {

    public EncryptStrategy strategy;

    public void setStrategy(EncryptStrategy strategy) {
this.strategy = strategy;
} public void encryptFile(File file){
this.strategy.encryptFile(file);
} public void decryptFile(File file){
this.strategy.decryptFile(file);
}
}

  4. 应用程序

public class Application {
public static void main(String[] args) {
File fileOne = new File("A.txt"); String s = "";
EncodeContext con = new EncodeContext();
con.setStrategy(new StrategyOne("Hello world!"));
con.encryptFile(fileOne);
System.out.println(fileOne.getName()+"加密后的內容:");
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 (IOException e) {
e.printStackTrace();
} }
}

Java的设计模式(5)-- 策略模式的更多相关文章

  1. Java的设计模式----strategy(策略模式)

    设计模式: 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开 ...

  2. [java之设计模式]策略模式

    策略模式(strategy pattern) 定义>> 将一系列的算法封装到一些列的类里面,并且可以相互替换 作用>> 将算法的变化独立于客户端,将算法的指责和算法的行为分开, ...

  3. 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查

    原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...

  4. [design-patterns]设计模式之一策略模式

    设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...

  5. 设计模式:策略模式(Strategy)

    定   义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...

  6. PHP设计模式之策略模式

    前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...

  7. JavaScript设计模式之策略模式(学习笔记)

    在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...

  8. 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

    原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...

  9. JavaScript设计模式之策略模式

    所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...

  10. 设计模式入门,策略模式,c++代码实现

    // test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...

随机推荐

  1. 【Python 代码】3D TIF 拆成若干张tif (ISBI细胞数据集)

    from libtiff import * imgdir = TIFF3D.open("train-labels.tif") imgarr = imgdir.read_image( ...

  2. com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-418, SQLSTATE=42610, SQLERRMC=null

    写了一条sql,在db2数据库中可以执行,但是转换成mybatis的mapper文件后,在执行排序操作时报该错误. 我排序是这样写的 <if test="orderStr != nul ...

  3. Qt 中的对象模型(Object Model)

    原标题:Qt 中的对象模型(Object Model)90不太后,余生皆折腾 本节内容主要讲了 Qt 对象模型比标准 C++ 对象模型多了什么内容,并介绍了组成 Qt 对象模型基础的相关的类.最后说明 ...

  4. js中const,var,let区别与用法(转)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qq_36784628/article/d ...

  5. ubuntu二进制包安装openresty

    date: 2019-08-01 17:59:59 author: headsen chen # 导入我们的 GPG 密钥: wget -qO - https://openresty.org/pack ...

  6. SNAT场景模拟

    我的网络配置跟教程中的这个略有不同: web server:192.168.66.101 nat server:192.168.66.188:192.168.6.172 client:192.168. ...

  7. 004-行为型-02-模板方法模式(Template Method)

    一.概述 定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤 1.1.适用场景 一次性实现一个算法的不变的部分,并将可变的行 ...

  8. JSOUP 爬虫

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.mavne 依赖: <!--html 解析 : jsoup HTML parser library @ ...

  9. Python高级笔记(八)with、上下文管理器

    1. 上下文管理器 __enter__()方法返回资源对象,__exit__()方法处理一些清除资源 如:系统资源:文件.数据库链接.Socket等这些资源执行完业务逻辑之后,必须要关闭资源 #!/u ...

  10. auto和decltype的用法总结

    一, auto 1, auto的作用     一般来说, 在把一个表达式或者函数的返回值赋给一个对象的时候, 我们必须要知道这个表达式的返回类型, 但是有的时候我们很难或者无法知道这个表达式或者函数的 ...