Chinaunix首页 | 论坛 | 博客
  • 博客访问: 282831
  • 博文数量: 69
  • 博客积分: 2946
  • 博客等级: 少校
  • 技术积分: 800
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-09 04:15
文章分类

全部博文(69)

文章存档

2013年(6)

2012年(16)

2011年(18)

2010年(29)

分类: Java

2013-01-20 01:20:55

策略模式是对算法进行封装的一种方法,将算法和算法的使用解耦出来。一类的算法都实现相同的接口,将这些不同的算法包装到一系列的策略类里。客户端通过实现对接口的调用,按照需求调用所需的策略,使用其中包装的算法,达到所需的目的。

image 图.1

从上图可以清晰的知道,在这个模式中主要涉及三个参与者,客户端(上下文,Context),抽象策略及具体策略。

客户端,持有抽象策略的引用,通过该引用来调用具体策略中的算法。

抽象策略,是具体策略所共有的接口,一般由接口来充当其角色,给出了具体策略所要实现的接口。

具体策略,实现抽象策略所有的接口,将每种具体的算法包装到具体的策略中。

很多书和博客中给出的例子,大多数都是关于购物折扣问题的,这个问题比较简单易懂。意思就是通过策略模式将原本的判断逻辑和算法执行过程分离开来。当需要新的计算方法时,添加一个实现该抽象策略接口新的具体策略类,通过该新的具体策略类来实现该功能。对系统原有代码不需做任何修改。形象一点来说,系统需要一个新配件,我们按照系统规范做一个新配件,安装到系统中去,系统可以实现完美调用的这个过程。

在这篇博文中,我举一个计算文件摘要的例子。常用的计算摘要的算法主要是MD5,SHA-1,SM3等算法。我们现在并不关心它们计算的细节有何差别,只需要知道一点--它们都是将输入的字符或字符串经过一系列复杂的计算输出一定长度的字符串(尽管它们输出字符串长度不一定相同)。

定义一个公共的接口Hash:

1: public interface Hash {
2:  
3:  public byte[] digest(byte[] str);
4:  public byte[] digest(String str);
5: }

三个具体策略类如下

MD5Digest:

 1: public class MD5Digest implements Hash {
 2:  
 3:  public byte[] digest(byte[] str) {
 4:  byte[] digest = new byte[16];
 5:  //MD5计算过程
 6:  return digest;
 7:  }
 8:  
 9:  public byte[] digest(String str) {
10:  byte[] digest = new byte[16];
11:  //MD5计算过程
12:  return digest;
13:  }
14: }

SHADigest:

 1: public class SHA1Digest implements Hash {
 2:  
 3:  public byte[] digest(byte[] str) {
 4:  byte[] digest = new byte[32];
 5:  //SHA-1 计算过程得到digest
 6:  return digest;
 7:  }
 8:  
 9:  public byte[] digest(String str) {
10:  byte[] digest = new byte[32];
11:  //SHA-1 计算过程得到digest
12:  return digest;
13:  }
14: }

SM3Digest:

 1: public class SM3Digest implements Hash {
 2:  
 3:  public byte[] digest(byte[] str) {
 4:  byte[] digest = new byte[32];
 5:  //SM3 计算过程得到digest
 6:  return digest;
 7:  }
 8:  
 9:  public byte[] digest(String str) {
10:  byte[] digest = new byte[32];
11:  //SM3计算过程得到digest
12:  return digest;
13:  }
14: }

客户端即上下文类为:

 1: public class Context {
 2:  
 3:  Hash hash = null;
 4:  byte[] digest = null;
 5:  public Context(Hash hast){
 6:  this.hash = hast;
 7:  }
 8:  
 9:  public void calculate(String str){
10:  digest = hash.digest(str);
11:  }
12: }

从上面的叙述中,可以总结一下,在什么情况下适合使用策略模式

  • 系统中有一组算法,可以将这组算法抽象出一个公共的接口,并且可以动态的选择执行那种算法的过程。
  • 系统中有逻辑判断,通过判断的结果来选择执行的算法。
  • 系统中有一组算法和数据,但是不允许客户知道算法执行的具体细节和数据。

策略模式的优点:

  • 省去了系统中的判断逻辑,便于系统后续维护;
  • 满足“开-闭”原则,方便系统的后续扩展;
  • 提供了管理算法的方法。特别是有等级的算法族时,恰当的利用继承关系,将公共代码转移到上一级中,从而避免代码的重复;
  • 避免过度的使用继承,使系统中不适合的功能出现在某些类中。

策略模式的缺点:

  • 当算法过多时,系统中具体策略类数量比较多,不方便系统维护;
  • 客户需要知道具体算法对应的算法类,然后才能调用其具体对应的类,增加了客户的负担。
阅读(1380) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~