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

  • 策略(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. thymeleaf错误解决办法

    Caused by: org.attoparser.ParseException: Exception evaluating SpringEL expression: "username&q ...

  2. linux下anaconda使用教程

    安装Anaconda.在命令行输入,下载anaconda.wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh. ...

  3. windows10 命令行修复系统引导

    文章介绍的方法适用于拥有一个刻录有原版win10安装镜像的用户 下载地址:https://www.microsoft.com/zh-cn/software-download/windows10 首先进 ...

  4. Windows使用telnet验证服务端口是否通

    使用telnet指令时,Windows需要开启Telnet服务. telnet不通的情况: a.端口对应的服务没启动,或者启动了服务端口不是对应的测试端口. b.端口受限不能访问. 以下内容转自:ht ...

  5. VS2019,打开项目之后显示:System.NullReferenceException: 未将对象引用设置到对象的实例

    关闭项目,删除项目文件夹下的隐藏文件夹.vs和bin/obj文件夹

  6. ADT中创建Android的Activity

    去创建Activity New->Other->Android->Android Activity->BlankActivity: 输入对应的信息: 创建完毕后,可以看到新建了 ...

  7. Android页面切换

    参考地址: http://www.crifan.com/android_how_to_create_new_ui_and_switch_to_another_new_ui/ 想要实现,在Android ...

  8. Leetcode: Campus Bikes II

    On a campus represented as a 2D grid, there are N workers and M bikes, with N <= M. Each worker a ...

  9. ABAP语法篇2 内表操作语法

    VALUE MOVE-CORRESPONDING CORRESPOING FOR REDUCE GROUP BY FILTER VALUE语法: 结构赋值 ... VALUE dtype | #(  ...

  10. 网络编程之Reactor 模式

    基本的架构是 epoll+线程池. 这篇博文主要从以下几个方面进行阐述: (1)reactor模式的一个介绍:(只要是我的理解) (2)关于线程池的说明. (3)如何将epoll + 池结合起来实现一 ...