Java的设计模式(5)-- 策略模式
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换,本模式使得算法可以独立于使用它的客户而变化。策略模式包括以下三种角色
- 策略(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)-- 策略模式的更多相关文章
- Java的设计模式----strategy(策略模式)
设计模式: 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精髓所在,我所理解的“简单”就是一把钥匙开 ...
- [java之设计模式]策略模式
策略模式(strategy pattern) 定义>> 将一系列的算法封装到一些列的类里面,并且可以相互替换 作用>> 将算法的变化独立于客户端,将算法的指责和算法的行为分开, ...
- 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查
原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...
- [design-patterns]设计模式之一策略模式
设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...
- 设计模式:策略模式(Strategy)
定 义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...
- PHP设计模式之策略模式
前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...
- JavaScript设计模式之策略模式(学习笔记)
在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- JavaScript设计模式之策略模式
所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...
- 设计模式入门,策略模式,c++代码实现
// test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...
随机推荐
- 线程池(4)-参数-RejectedExecutionHandler
1.介绍 当线程池线程数大于最大线程数(maximumPoolSize)时,多余的任务,程序应该按照什么拒绝策略处理. 2.拒绝策略4个 AbortPolicy:丢弃任务,并抛出RejectedExe ...
- 在应用中显示的图片很多情况不满足业务需求,我们需要动态根据图片的宽高进行缩放或加载中显示的缺省图片,这是我没就需要监听图片加载完成回调,来看看微信小程序怎么实现图片加载完成回调。
<swiper-item> <image src="{{item.image}}" class="slide-image" mode=&quo ...
- nginx压力测试和并发预估
一.Nginx并发预估 预估算法:{(?G)*1024-system}/请求大小 (?G):表示内存大小1024:表示内存容量标准进制system:表示系统和服务占用的额外内存和需要预留的内存请求大小 ...
- html常用标签详解
html常用标签详解 一.总结 一句话总结: 这些资料没必要自己总结,可以直接网上找,简单方便,再根据需求改一下 二.HTML常用标签详解 转自或参考:HTML常用标签详解https://blog.c ...
- CMU Database Systems - Timestamp Ordering Concurrency Control
2PL是悲观锁,Pessimistic,这章讲乐观锁,Optimistic,单机的,非分布式的 Timestamp Ordering,以时间为序,这个是非常自然的想法,按每个transaction的时 ...
- 5+app uni-app flutter
5+app uni-app flutter三者区别是什么? - 知乎 https://www.zhihu.com/question/295107584/answer/525442299 崔红保 DCl ...
- Android中jsoup的混淆规则【转】
Android中jsoup的混淆规则版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com 说实话这篇文章的标题和内容我觉得很水,所以读者们要是也觉得这篇文章 ...
- #软件更新#Visual Studio更新到16.3.8
#软件更新#Visual Studio更新到16.3.8 此次更新包括以下内容:(1)支持Xcode 11.2.(2)修复无法从System.String类型转化的bug.(3)修复UWP开发中,加载 ...
- OctetString 转String
/// <summary> /// OctetString转时间 /// </summary> /// <param name="ss">字符串 ...
- DRBD UpToDate/DUnknown 故障恢复
故障如下: root@drbd1:~# drbd-overview 0:data/0 StandAlone Primary/Unknown UpToDate/DUnknown /data/mysql ...