定义一系列的算法(algorithm family),将每一个算法封装起来,并让它们可以相互替换(interchangeable),策略模式让算法独立于使用它的客户而变化。
类和对象的关系
抽象策略类(Strategy):定义一个公共的接口给所支持的算法。Context使用这个接口调用Concrete Strategy定义的算法。
具体策略类(Concrete Strategy):调用Strategy接口实现具体的算法。
场景(Context):用Concrete Strategy对象配置其执行环境,维护一个对Strategy的引用实例,可以定义一个接口供Strategy存取其数据。
范例
我们打算去机场乘飞机,可以选择很多交通方法。我们可以根据时间要求和乘车费用及方便性而采用不同的策略。
优势和缺陷
策略模式提供了替代派生子类,并定义类的每个行为,剔除了代码中条件的判断语句,使得扩展和结合新的行为变得更容易,根本不需要变动应用程序。策略模式可以避免使用多重田间转移语句,系统变得更加灵活。应用策略模式会长生很多子类,这符合高内聚的责任分配模式。
应用情景
1. 多个类的分别只是在于行为的不同。
2. 你需要对行为的算法做很多变动
3. 客户不知道算法要使用的数据。
Strategy
模式使用例子
1. 以不同的格式保存文档
2. 以不同的算法压缩文件
3. 以不同的算法截取图像
在这里以字符串为例,一个文件,我们需要读取后,希望替代其中相应的变量,然后输出。关于替代其中的变量的方法可能有很多种方法,这取决于用户的要求,所以我们要准备几套变量字符代替方案。
定义一个公共的接口给所有支持的算法,这个抽象类Strategy定义了一些方法和变量
package
StrategyPattern;
public
abstract
class
Strategy {
protected
String
oldString
;
protected
String
newString
;
public
Strategy(String oldString) {
this
.
oldString
= oldString;
}
public
String getNewString() {
return
newString
;
}
//
子类继承这个方法,实现不同的替换
public
abstract
void
replay();
}
|
现在又三个字符串的替换方法:
1.”aaa”
à “bbb”
2.”aaa”
à “ccc”
3.”aaa”
à “ddd”
有三个类完成的这样的功能,它们分别是
ConcreteStrategyOne
、
ConcreteStrategyTwo
、
ConcreteStrategyThree
这三个类都分别继承了类
Strategy
,并实现了
replay()
方法。
package
StrategyPattern;
public
class
ConcreteStrategyOne
extends
Strategy {
public
ConcreteStrategyOne(String oldString) {
super
(oldString);
}
@Override
public
void
replay() {
newString
=
oldString
.replace(
"aaa"
,
"bbb"
);
System.
out
.println(
newString
);
System.
out
.println(
"successfully replace by one model"
);
}
}
package
StrategyPattern;
public
class
ConcreteStrategyTwo
extends
Strategy {
public
ConcreteStrategyTwo(String oldString) {
super
(oldString);
//
TODO
Auto-generated constructor stub
}
@Override
public
void
replay() {
//
TODO
Auto-generated method stub
newString
=
oldString
.replace(
"aaa"
,
"ccc"
);
System.
out
.println(
newString
);
System.
out
.println(
"successfully replace by two medol"
);
}
}
|
package
StrategyPattern;
public
class
ConcreteStrategyThree
extends
Strategy {
public
ConcreteStrategyThree(String oldString) {
super
(oldString);
//
TODO
Auto-generated constructor stub
}
@Override
public
void
replay() {
//
TODO
Auto-generated method stub
newString
=
oldString
.replace(
"aaa"
,
"ddd"
);
System.
out
.println(
newString
);
System.
out
.println(
"successfull replace by three model"
);
}
}
|
下面定义一个算法解决类,让用户可以自由的选择算法
package
StrategyPattern;
public
class
Context {
private
Strategy
strategy
;
ackage
StrategyPattern;
public
class
Context {
private
Strategy
strategy
;
public
Context(Strategy strategy) {
this
.
strategy
= strategy;
}
public
void
getNewContext(String str) {
strategy
.replay();
}
public
void
changeAlgorithm(Strategy strategy) {
this
.
strategy
= strategy;
}
}
|
调试类如下:
package
StrategyPattern;
public
class
Client {
public
static
void
main(String[] args) {
String str =
"aaannnnnnnnnnnwwwwwwwww"
;
Strategy one =
new
ConcreteStrategyOne(str);
Strategy two =
new
ConcreteStrategyTwo(str);
Strategy three =
new
ConcreteStrategyThree(str);
Context context =
new
Context(one);
context.getNewContext(str);
context.changeAlgorithm(two);
context.getNewContext(str);
context.changeAlgorithm(three);
context.getNewContext(str);
}
}
|
我们达到了在运行期间可以自由的切换算法的目的。
Strategy
模式的核心在于抽象类
AbstractStrategy
类的使用,可以在运行期间实现算法的转换,策略模式在用户需要变化时修改量很少,而且快速。
Strategy
模式跟
Factory
模式有点相像,
Strategy
模式很容易理解,
Strategy
模式可以在运行时期自由切换,
Factory
模式主要是用来创建对象。