摘要:本文深入浅出的讲述了设计模式中的策略模式
,
并给出了简单的示例
,
例子浅显易懂
,
并附带源代码。
       
策略
模式属于行为模式,其意图是定义一系列算法,把他们一个个封装起来,并且使他们可以互相替换,本末实使得算法可以独立与使用它的客户而变化。在做文字输入软件的时候,有很多的算法可以对一个正文流进行分析,将这些算法硬编码进使用他们的类中是不可取的,其原因如下:
l         
需要换行功能的客户程序如果直接包含换行算法代码的话将会变得复杂,这使得客户程序大并且难以维护,尤其当需要支持多种换行算法时为会更严重。
l         
不同的是欧需要不同的算法,我们不想支持我们并不使用的换行算法。
l         
当换行功能是客户程序的一个难以分割的成分时,增加新的换行算法或改变现有算法将十分困难。
我们可以定义一些类来封装不同的换行算法,从而避免这些问题,一个以这种方法封装的算法成为策略。
例如一个把数组导出为表格的算法,输入一个数组,导出一个表格,当用户想改变导出的表格时,便可以通过改变输出的算法改变输出的结果。如果输出的内容用以网页显示,则输出
<table><tr><td>Jack</td></tr><tr><td>Maya</td></tr><tr><td>Mikes</td></tr><tr><td>Shadow</td></tr></table>
如果输出的结果用以直接的屏幕输出,则可以输出:
     +----+----+-----+------+
     |Jack|Maya|Mikes|Shadow|
     +----+----+-----+------+
相应的UML
如下图所示:
1
参与者:
       Strategy(
策略 TableExporter):
定义所有支持算法的公共接口。 Context
使用这个接口来调用某 ConcreteStrategy
定义的算法,
ConcreteStrategy(
具体策略,如 HtmlExporter):
              
Strategy
接口实现某具体算法。
Context(
上下文 : client)
    
       
用一个 ConcreteStrategy
对象来配置。
       
维护一个对 Strategy
对象的引用。
       
可定义一个接口来让 Strategy
访问它的数据。
协作关系: Strategy
Context
互相作用以实现选定的算法。当算法被调用时, Context
可以将该算法所需要的所有数据都传递给该 Strategy,
或者 Context
可以将自身作为一个参数传递给 Strategy
操作,这就让 Strategy
在需要时可以回调 Context
       Context
将它的客户的请求转发给他的 Strategy
。客户通常创建并传递一个 ConcreteStrategy
对象给该 Context
这样,客户仅与 Context
交互,通常有一系列的 ConcreteStrategy
类可以供客户从中选择。
适用性:
       
当存在以下情况时使用 Strategy
l         
许多相关的类仅仅是行为有差别,策略提供了一种多个行为中的一个行为来配置一个类的方法。
l         
需要使用一个算法的不同变体。
l         
算法使用客户不应该知道的数据。
l         
一个类定义了多种行为。
例子相关的代码:
TableExporter
代码:
       
package
 strategy;
public
 
interface
 TableExporter{
    
public
 String getExported(String[] data);
}
HtmlExporter
代码:
package
 strategy;
public
 
class
 HtmlExporter 
implements
 TableExporter{
    
public
 String getExported(String[] data){
       
if
(data == 
null
){
           
return
 
""
;
       }
       StringBuffer sb = 
new
 StringBuffer();
       sb.append(
"<table>"
);
       
for
(
int
 i=0;i<data.
length
;i++)
           sb.append(
"<tr><td>"
+data[i]+
"</td></tr>"
);
       sb.append(
"</table>"
);
       
return
 sb.toString();
    }
}
LineExporter
代码:
package
 strategy;
public
 
class
 LineExporter 
implements
 TableExporter{
    
public
 String getExported(String[] data){
       
if
(data == 
null
){
           
return
 
""
;
       }
       StringBuffer top = 
new
 StringBuffer(
"+"
);
       StringBuffer mid = 
new
 StringBuffer(
"|"
);
       
for
(
int
 i =0;i<data.
length
;i++){
           String str = data[i];
           
for
(
int
 j=0;j<str.length();j++)
              top.append(
"-"
);
          
           mid.append(str);
           top.append(
"+"
);
           mid.append(
"|"
);
       }
       top.append(
"\n"
);
       mid.append(
"\n"
);
       
return
 top.toString()+mid.toString()+top.toString();
    }
}
Client
代码:
package
 strategy;
public
 
class
 Client{
    
public
 
static
 
void
 main(String[] args){
       String[] data = 
new
 String[]{
"Jack"
,
"Maya"
,
"Mikes"
,
"Shadow"
};
       TableExporter tb;
       tb = 
new
 HtmlExporter();
       System.
out
.println(tb.getExported(data));
       tb = 
new
 LineExporter();
       System.
out
.println(tb.getExported(data));
    }
}
总结: Strategy
策略使得改变一个算法的实现比较容易,在 Java
中的组件的布局便采用了策略模式,使用靠昨对齐还是居中对齐只是算法的区别。