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

  • 策略(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. Android中活动的最佳实践(如何很快的看懂别人的代码activity)

    这种方法主要在你拿到别人的代码时候很多activity一时半会儿看不懂,用了这个方法以后就可以边实践操作就能够知道具体哪个activity是干什么用的 1.新建一个BaseActivity的类,让他继 ...

  2. 加入购物车的功能wepy

    1.先有一个加入购物车的按钮 <view wx:if="{{(detaildata.boughtNum < detaildata.buy_limit) && de ...

  3. NAT端口映射综合详解

  4. git 代码版本回退

    1.查看 commit id 2.git reset --hard "dfdfdfdf" // commit id 3.git push -f -u origin 2.1.0 // ...

  5. Win10 剪贴板 快捷键是什么?

      使用基于云的剪贴板从一台电脑上复制图像和文本并粘贴到另一台电脑上.你不仅可以从剪贴板历史记录中粘贴,还可以固定你发现自己经常使用的项目. 若要随时访问剪贴板历史记录,请按 Windows 徽标键  ...

  6. CMU Advanced DB System - Query Optimizer

    Overview Optimizer模块所处在的位置如图, 那么做optimize的目的是, 找出所有‘correct’执行计划中‘cost’最低的 那么这里首先要明确的概念,‘correct’,关系 ...

  7. Eclipse/STS选择一段文本进行复制变得很卡的解决方案

    网上给出的解决方案是: 更改打开代码超链接按键Ctrl为Alt:Window -> Preferences -> General -> Editors -> Text Edit ...

  8. python 设计模式之单例模式 Singleton Pattern

    #引入 一个类被设计出来,就意味着它具有某种行为(方法),属性(成员变量).一般情况下,当我们想使用这个类时,会使用new 关键字,这时候jvm会帮我们构造一个该类的实例.这么做会比较耗费资源. 如果 ...

  9. crontab 使用日期时间命名重定向文件

    使用月份命名 0 12 * * * sh /tmp/test.sh >> "/tmp/$(date +"\%Y-\%m").log" 2>&a ...

  10. js 解析 JSON 数据

    JSON 数据如下: { "name": "mkyong", , "address": { "streetAddress" ...