⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 strategypattern.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>





  
  
  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">





  
  
  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">





  
  
  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">





  
  
  
  
  
  <title>Strategy 模式</title>
</head>


<body>





<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>





<h1><a href="CppGossip.html">Design Pattern:&nbsp;Strategy 模式</a></h1>

考虑您要设计一个更换各种符号的工具类TextCharChange,您是否会采用这样的方式:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">public void replace() { </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp; switch(getChangeType()) { </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case RN_TYPE:&nbsp;&nbsp; replaceRN(); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
break; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case N_TYPE: replaceN(); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
break; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case OTHER_TYPE: replaceOTHER(): </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
break; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">&nbsp;&nbsp; } </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">}</span><br>
</div>
&nbsp;<br>
这么作的缺点是,日后您要增加更换符号的策略时,会有几个地方需要修改:增加TYPE常数、增加TextCharChange中的 replaceXXX()方法、增加 replace()方法中的switch case判断。<br>
<br>
像这种策略采用的情况,可以将策略加以封装为一个物件,而不是将策略写死在某个类中,如此一来,策略可以独立于客户端,随时增加变化、增加或减少策略,即使是修改每个策略的内容,也不会对客户端程式造成影响。<br>
<br>
来举个最简单的例子,首先要知道Windows与Linux的文字档案换行符号是不同的,Windows是 /r/n ,而Linux是 /n,今天您要设计一个文字编辑器,在适当的时候,您必须要能随时转换这两种符号,如果不采用上面的策略采用流程的话,要如何设计:<br>
<ul>
  <li> TextStrategy.java
  </li>
</ul>

<pre>public abstract class TextStrategy { <br>    protected String text;<br><br>    public TextStrategy(String text) { <br>        this.text = text; <br>    }<br><br>    public abstract String replace(); <br>}  <br></pre>

<br>

<ul>
  <li> LinuxStrategy.java
  </li>
</ul>

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

<br>

<ul>
  <li> WindowsStrategy.java
  </li>
</ul>

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

<br>

<ul>
  <li> TextCharChange.java
  </li>
</ul>

<pre>public class TextCharChange { <br>    public static void replace(TextStrategy strategy) { <br>        strategy.replace(); <br>    } <br>} <br></pre>

<br>

<ul>
  <li> Main.java
  </li>
</ul>

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

<br>
为了明显的秀出结果,我们使用@n来表示 '/n' , @r 表示 '/r' 符号,Main中的流程是个假设的情况,何时采用何种策略是随机的。<br>
<br>
在Strategy模式中,使用一个公开的介面replace(),让客户端请求,而在实作replace()时,可以任意的组合演算策略,程式中的
preOperation()、postOperation()就是用以示意演算的组合概念,Strategy模式封装了这些演算过程,使它们易于组合、
修改、替换,上面这个例子的UML 类别结构图如下所示: <br>
<div style="text-align: center;"><img style="width: 455px; height: 151px;" alt="Strategy" title="Strategy" src="images/strategy-1.jpg"><br>
</div>
<br>
Strategy模式的UML类别结构图如下:<br>
<div style="text-align: center;"><img style="width: 575px; height: 168px;" alt="Strategy" title="Strategy" src="images/strategy-2.jpg"></div>
从行为上来说,<a href="StatePattern.htm">State 模式</a> 与Strategy模式是蛮相近的。<br>
<br>
State模式:看当前是什么状态,就采取什么动作。<br>
<br>
Strategy模式:看需求(情境)是什么,采用适当的策略。<br>
<br>
不过两者虽相似,应用的场合稍有不同,State模式中有一个重点在于设定状态变化,就像 Gof 例子中举的TCP连线;Strategy策略模式则是直接采用适当的策略的感觉,例如Gof中说的,采用适当的演算法来作正文换行。<br>
<br>
<br>





</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -