策略设计模式是一种行为设计模式,我们在运行时为同一任务从多个其他实现中选择特定的算法或任务实现。 重要的一点是,这些实现是可互换的——基于任务的实现可以在不影响应用程序工作流的情况下被选择。
介绍
策略模式包括从宿主类中删除一个算法,并将其放在单独的类中,以便在相同的编程上下文中可能存在不同的算法(即策略),这些算法可以在运行时选择。 策略模式允许客户端代码从一系列相关但不同的算法中进行选择,并提供了一种在运行时根据客户端上下文选择任何算法的简单方法。
由开/闭原理 这种模式基于开/闭原则。我们不需要修改上下文[close for modify],但是可以选择并添加任何实现[open for extension]。 例如,在Collections.sort()中,我们不需要更改sort方法来实现不同的排序结果。我们可以在运行时提供不同的比较器。
##设计 在策略模式中,我们首先创建算法的抽象。这是一个具有抽象操作的接口。然后我们创建这个抽象的实现,这些被称为策略。 客户机总是调用抽象,并传递上下文对象。这个上下文对象将决定使用哪个策略。
解决问题
让我们来解决一个设计问题,以便更详细地理解策略模式。 我想设计一个社交媒体应用程序,让我可以连接到所有四个社交平台上的朋友,例如Facebook,谷歌Plus, Twitter和Orkut(例如sake)。现在我希望客户端能够说出朋友的名字和想要的平台-然后我的应用程序应该透明地连接到他。 更重要的是,如果我想在应用程序中添加更多的社交平台,那么应用程序代码应该在不破坏设计的情况下适应它。
策略设计模式的解决方案
在上述问题中,我们有一个操作可以通过多种方式完成(连接到朋友),用户可以在运行时选择所需的方式。因此,它是战略设计模式的良好候选。 为了实现解决方案,让我们一次设计一个参与者。
- ISocialMediaStrategy—抽象操作的接口。
- SocialMediaContext—决定实现的上下文。
- Implementation-ISocialMediaStrategy的各种实现。例如facebook战略,GooglePlusStrategy, TwitterStrategy和OrkutStrategy。
类图
代码实现
ISocialMediaStrategy.java
1
2
3
4
5
package com.howtodoinjava.designpattern.strategy;
public interface ISocialMediaStrategy{
public void connectTo(String friendName);
}
SocialMediaContext.java
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.howtodoinjava.designpattern.strategy;
public class SocialMediaContext{
ISocialMediaStrategy smStrategy;
public void setSocialmediaStrategy(ISocialMediaStrategy smStrategy){
this.smStrategy = smStrategy;
}
public void connect(String name){
smStrategy.connectTo(name);
}
}
FacebookStrategy.java
1
2
3
4
5
6
7
8
9
10
package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class FacebookStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName){
System.out.println("Connecting with " + friendName + " through Facebook");
}
}
GooglePlusStrategy.java
1
2
3
4
5
6
7
8
9
10
package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class GooglePlusStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName){
System.out.println("Connecting with " + friendName + " through GooglePlus");
}
}
TwitterStrategy.java
1
2
3
4
5
6
7
8
9
10
package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class TwitterStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName){
System.out.println("Connecting with " + friendName + " through Twitter");
}
}
Demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.howtodoinjava.designpattern.strategy.demo;
import com.howtodoinjava.designpattern.strategy.SocialMediaContext;
import com.howtodoinjava.designpattern.strategy.impl.FacebookStrategy;
import com.howtodoinjava.designpattern.strategy.impl.GooglePlusStrategy;
import com.howtodoinjava.designpattern.strategy.impl.OrkutStrategy;
import com.howtodoinjava.designpattern.strategy.impl.TwitterStrategy;
public class Demo {
public static void main(String[] args) {
// Creating social Media Connect Object for connecting with friend by
// any social media strategy.
SocialMediaContext context = new SocialMediaContext();
// Setting Facebook strategy.
context.setSocialmediaStrategy(new FacebookStrategy());
context.connect("Lokesh");
System.out.println("====================");
// Setting Twitter strategy.
context.setSocialmediaStrategy(new TwitterStrategy());
context.connect("Lokesh");
System.out.println("====================");
// Setting GooglePlus strategy.
context.setSocialmediaStrategy(new GooglePlusStrategy());
context.connect("Lokesh");
System.out.println("====================");
// Setting Orkut strategy.
context.setSocialmediaStrategy(new OrkutStrategy());
context.connect("Lokesh");
}
}
输出结果:
1
2
3
4
5
6
7
Connecting with Lokesh through Facebook
====================
Connecting with Lokesh through Twitter
====================
Connecting with Lokesh through GooglePlus
====================
Connecting with Lokesh through Orkut [not possible though :)]
总结
该模式定义了一组相关算法,并将它们封装在单独的类中,允许客户端在运行时选择任何算法 它允许在不修改现有算法或使用算法或策略的上下文类的情况下添加新算法 策略模式是基于实体原则的开闭设计原则。 sort()和Comparator接口的组合是策略模式的一个很好的例子。