读书人

Design Pattern: Strategy 形式

发布时间: 2012-09-07 10:38:15 作者: rapoo

Design Pattern: Strategy 模式

Strategy策略模式是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.

Stratrgy应用比较广泛,比如, 公司经营业务变化图, 可能有两种实现方式,一个是线条曲线,一个是框图(bar),这是两种算法,可以使用Strategy实现.

这里以字符串替代为例, 有一个文件,我们需要读取后,希望替代其中相应的变量,然后输出.关于替代其中变量的方法可能有多种方法,这取决于用户的要求,所以我们要准备几套变量字符替代方案.

?

考虑您要设计一个更换各种符号的工具类TextCharChange,您是否会采用这样的方式:

public void replace() {
?? switch(getChangeType()) {
????? case RN_TYPE:?? replaceRN();
????????????????????????? break;
????? case N_TYPE: replaceN();
????????????????????????? break;
????? case OTHER_TYPE: replaceOTHER():
????????????????????????? break;
????? ...
?? }
}

?
这么作的缺点是,日后您要增加更换符号的策略时,会有几个地方需要修改:增加TYPE常数、增加TextCharChange中的 replaceXXX()方法、增加 replace()方法中的switch case判断。

像这种策略采用的情况,可以将策略加以封装为一个物件,而不是将策略写死在某个类中,如此一来,策略可以独立于客户端,随时增加变化、增加或减少策略,即使是修改每个策略的内容,也不会对客户端程式造成影响。

来举个最简单的例子,首先要知道Windows与Linux的文字档案换行符号是不同的,Windows是 /r/n ,而Linux是 /n,今天您要设计一个文字编辑器,在适当的时候,您必须要能随时转换这两种符号,如果不采用上面的策略采用流程的话,要如何设计:

TextStrategy.java
public abstract class TextStrategy {     protected String text;    public TextStrategy(String text) {         this.text = text;     }    public abstract String replace(); }  

?

LinuxStrategy.java
public class LinuxStrategy extends TextStrategy {     public LinuxStrategy(String text) {         super(text);     }    public String replace() {         preOperation();         System.out.println(               text = text.replaceAll("@r@n", "@n"));         postOperation();         return text;     }    private void preOperation() {         System.out.println("LinuxStrategy preOperation");     }    private void postOperation() {         System.out.println("LinuxStrategy postOperation");     } }  

?

WindowsStrategy.java
public class WindowsStrategy extends TextStrategy {     public WindowsStrategy(String text) {         super(text);     }    public String replace() {         startOperation();         System.out.println(                     text = text.replaceAll("@n", "@r@n"));         endOperation();         return text;     }    private void startOperation() {         System.out.println("WindowsStrategy startOperation");     }     private void endOperation() {         System.out.println("WindowsStrategy endOperation");     } } 

?

TextCharChange.java
public class TextCharChange {     public static void replace(TextStrategy strategy) {         strategy.replace();     } } 

?

Main.java
public class Main {     public static void main(String[] args) {         String linuxText =             "This is a test text!!@n Oh! Line Return!!@n";         String windowsText =             "This is a test text!!@r@n Oh! Line Return@r@n";         // load file, suppose it's Linux's text file         // take the WindowsStrategy         // I want to change it to Windows' text file         TextCharChange.replace(              new WindowsStrategy(linuxText));         // such-and-such operation.....         System.out.println();         // load file, suppose it's Windows' text file         // take the LinuxStrategy         // I want to change it to Linux's text file         TextCharChange.replace(            new LinuxStrategy(windowsText));     } } 


为了明显的秀出结果,我们使用@n来表示 '/n' , @r 表示 '/r' 符号,Main中的流程是个假设的情况,何时采用何种策略是随机的。

在Strategy模式中,使用一个公开的介面replace(),让客户端请求,而在实作replace()时,可以任意的组合演算策略,程式中的 preOperation()、postOperation()就是用以示意演算的组合概念,Strategy模式封装了这些演算过程,使它们易于组合、修改、替换.

?

从行为上来说,State 模式 与Strategy模式是蛮相近的。

State模式:看当前是什么状态,就采取什么动作。

Strategy模式:看需求(情境)是什么,采用适当的策略。

不过两者虽相似,应用的场合稍有不同,State模式中有一个重点在于设定状态变化,就像 Gof 例子中举的TCP连线;Strategy策略模式则是直接采用适当的策略的感觉,例如Gof中说的,采用适当的演算法来作正文换行。

实际整个Strategy的核心部分就是抽象类的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速.

Strategy和Factory有一定的类似,Strategy相对简单容易理解,并且可以在运行时刻自由切换。Factory重点是用来创建对象。

Strategy适合下列场合:

1.以不同的格式保存文件;

2.以不同的算法压缩文件;

3.以不同的算法截获图象;

4.以不同的格式输出同样数据的图形,比如曲线 或框图bar等

?

读书人网 >软件架构设计

热点推荐