内容简介:定义一系列算法,封装每个算法,并使它们可互换。策略模式允许算法独立于使用它的客户端。
目的
定义一系列算法,封装每个算法,并使它们可互换。策略模式允许算法独立于使用它的客户端。
解释
为了解释现实世界中的策略,让我们以软件开发人员为例。如果语言不是问题,我可能会要求开发人员为我编写一段代码来创建用户界面。一个开发者选择的语言是Java,所以他将用Swing开发UI。同时,另一个开发人员决定使用C。我不介意,我已经把如何编写UI的细节留给了开发人员,并且他们都应用了自己的策略。在任何阶段,开发人员都可以改变他们的策略,如果他们觉得有必要,可以选择使用不同的语言。所有这些都是关于动态变化的行为。
技术示例
1.策略模式的最佳示例之一是采用Comparator参数的 Collections.sort() 方法。基于Comparator接口的不同实现,对象将以不同的方式进行排序。
2.策略模式的另一个用途是以不同格式保存文件,运行各种 排序 算法或文件压缩。
3.要执行诸如加法,减法,除法和乘法等数学运算,我们需要决定在运行时执行哪个运算。
结构
参与者
1.策略(Strategy)
- 声明所有支持的算法共有的接口。
- context使用此接口来调用ConcreteStrategy定义的算法。
2.具体策略 ConcreteStrategy
- 使用Strategy接口实现算法。
3.上下文 (Context)
- 配置了ConcreteStrategy对象。
- 维护对Strategy对象的引用。
- 可以定义一个让Strategy访问其数据的接口。
合作
- 策略和上下文交互以实现所选算法。当调用算法时,上下文可以将算法所需的所有数据传递给策略。或者,上下文可以将自己作为参数传递给策略操作。这使策略可以根据需要调用上下文。
- 上下文将客户的请求转发给其策略。客户端通常创建一个具体的策略对象并将其传递给上下文;此后,客户端专门与上下文进行交互。通常有一系列具体的策略类供客户选择。
让我们看看它是如何在 Java 中运行的。
1.实现( 数学运算作为算法)
请参阅此实现的 结构图 ,并按照 结构图 创建组件 。
第1步:创建一个类似Strategy.java的界面
<b>public</b> <b>interface</b> Strategy {
<b>public</b> <b>int</b> doOperation(<b>int</b> num1, <b>int</b> num2);
}
第2步:创建实现相同接口的具体类。
OperationAdd.java
<b>public</b> <b>class</b> OperationAdd implements Strategy{
@Override
<b>public</b> <b>int</b> doOperation(<b>int</b> num1, <b>int</b> num2) {
<b>return</b> num1 + num2;
}
}
OperationSubstract.java
<b>public</b> <b>class</b> OperationSubstract implements Strategy{
@Override
<b>public</b> <b>int</b> doOperation(<b>int</b> num1, <b>int</b> num2) {
<b>return</b> num1 - num2;
}
}
OperationMultiply.java
<b>public</b> <b>class</b> OperationMultiply implements Strategy{
@Override
<b>public</b> <b>int</b> doOperation(<b>int</b> num1, <b>int</b> num2) {
<b>return</b> num1 * num2;
}
}
operationDevision.java
<b>public</b> <b>class</b> OperationDevision implements Strategy{
@Override
<b>public</b> <b>int</b> doOperation(<b>int</b> num1, <b>int</b> num2) {
<b>return</b> (num1/num2);
}
}
第3步:创建 上下文 类。
Context.java
<b>public</b> <b>class</b> Context {
<b>private</b> Strategy strategy;
<b>public</b> Context(Strategy strategy){
<b>this</b>.strategy = strategy;
}
<b>public</b> <b>int</b> executeStrategy(<b>int</b> num1, <b>int</b> num2){
<b>return</b> strategy.doOperation(num1, num2);
}
}
第4步:使用 上下文 查看更改其策略时的行为更改 。
StrategyPatternDemo.java
<b>public</b> <b>class</b> StrategyPatternDemo {
<b>public</b> <b>static</b> <b>void</b> main(String[] args) {
Context context = <b>new</b> Context(<b>new</b> OperationAdd());
System.out.println(<font>"10 + 5 = "</font><font> + context.executeStrategy(10, 5));
context = <b>new</b> Context(<b>new</b> OperationSubstract());
System.out.println(</font><font>"10 - 5 = "</font><font> + context.executeStrategy(10, 5));
context = <b>new</b> Context(<b>new</b> OperationMultiply());
System.out.println(</font><font>"10 * 5 = "</font><font> + context.executeStrategy(10, 5));
}
}
</font>
第5步:验证输出。
10 + 5 = 15 10 - 5 = 5 10 * 5 = 50
2.实施(文件压缩工具)
请参阅 此实现的 结构图 ,并按照 结构图 创建组件 。 让我们使用文件压缩 工具 的例子 - 我们创建zip或rar文件。首先,我们需要一个策略:
<font><i>//Strategy Interface</i></font><font>
<b>public</b> <b>interface</b> CompressionStrategy {
<b>public</b> <b>void</b> compressFiles(ArrayList<File> files);
}
</font>
我们需要提供两个实现,一个用于zip,一个用于rar
<b>public</b> <b>class</b> ZipCompressionStrategy implements CompressionStrategy {
<b>public</b> <b>void</b> compressFiles(ArrayList<File> files) {
<font><i>//using ZIP approach</i></font><font>
}
}
</font>
<b>public</b> <b>class</b> RarCompressionStrategy implements CompressionStrategy {
<b>public</b> <b>void</b> compressFiles(ArrayList<File> files) {
<font><i>//using RAR approach</i></font><font>
}
}
</font>
我们的上下文将为客户端提供压缩文件的方法。假设我们的应用程序中有一个首选项设置,用于设置要使用的压缩算法。我们可以使用Context中的setCompressionStrategy方法更改策略。
<b>public</b> <b>class</b> CompressionContext {
<b>private</b> CompressionStrategy strategy;
<font><i>//this can be set at runtime by the application preferences</i></font><font>
<b>public</b> <b>void</b> setCompressionStrategy(CompressionStrategy strategy) {
<b>this</b>.strategy = strategy;
}
</font><font><i>//use the strategy</i></font><font>
<b>public</b> <b>void</b> createArchive(ArrayList<File> files) {
strategy.compressFiles(files);
}
}
</font>
很明显,所有客户端现在要做的就是将文件传递给CompressionContext。
<b>public</b> <b>class</b> Client {
<b>public</b> <b>static</b> <b>void</b> main(String[] args) {
CompressionContext ctx = <b>new</b> CompressionContext();
<font><i>//we could assume context is already set by preferences</i></font><font>
ctx.setCompressionStrategy(<b>new</b> ZipCompressionStrategy());
</font><font><i>//get a list of files...</i></font><font>
ctx.createArchive(fileList);
}
}
</font>
适用场景
- 许多相关类只在他们的行为上有所不同。策略模式提供了一种将类配置为多种行为之一的方法。
- 你需要不同的算法变体。例如,您可以定义反映不同空间/时间权衡的算法。当这些变体作为算法的类层次结构实现时,可以使用策略模式。
- 算法使用客户端不应该知道的数据。使用策略模式可避免暴露复杂的特定于算法的数据结构。
- 一个类定义了许多行为,这些行为在其操作中显示为多个条件语句。而不是很多条件,将相关的条件分支移动到自己的Strategy类中。
以上所述就是小编给大家介绍的《策略模式(Strategy Design Pattern)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Domain-Driven Design Distilled
Vaughn Vernon / Addison-Wesley Professional / 2016-6-2 / USD 36.99
Domain-Driven Design (DDD) software modeling delivers powerful results in practice, not just in theory, which is why developers worldwide are rapidly moving to adopt it. Now, for the first time, there......一起来看看 《Domain-Driven Design Distilled》 这本书的介绍吧!
UNIX 时间戳转换
UNIX 时间戳转换
RGB HSV 转换
RGB HSV 互转工具