0%

设计模式 | 策略模式

这个模式可以替代写 if else

我们使用的app大多都有分享的功能,我们可以选择分享到不同的地方,比如微博、微信、QQ等等,虽然是同一个内容,但是分享到不同的平台就会有不同的处理方式,比如要跳转到不同的app或者直接复制链接等等。如果让你来实现这个功能,你会如何实现呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void Share{
public void shareOptions(String option){
if(option.equals("微博")){
//function1();
//...
}else if(option.equals("微信")){
//function2();
//...
}else if(option.equals("朋友圈")){
//function3();
//...
}else if(option.equals("QQ")){
//function4();
//...
}
//...
}

如果只是写一个这么简单的功能,那么这样的代码也未尝不可,因为这样的代码量不多,后续也不需要怎么拓展和修改,维护起来也不算麻烦。但是,我们工作中遇到的都是一些比较复杂的项目,要保证项目的可读性、可维护性和可拓展性,就必须在代码上下功夫了。

策略模式中有哪些角色。

  • Strategy(策略)

    • Strategy角色负责决定实现策略所必需的接口(API)。在示例程序中,由strategy接口扮演此角色。
  • ConcreteStrategy(具体的策略)

    • ConcreteStrategy角色负责实现Strategy角色的接口(API),即负责实现具体的策略(战略、方向、方法和算法)。
  • Context(上下文)

    • 负责使用Strategy角色。Context角色保存了ConcreteStrategy角色的实例,并使用ConcreteStrategy角色去实现需求(总之,还是要调用Strategy角色的接口(API))。

介绍到这里,相信你对策略模式有了初步的认识,那我们就用策略模式来重构前面的代码,让你加深对策略模式的理解。

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
//定义策略接口
public interface DealStrategy{
void dealMythod(String option);
}

//定义具体的策略1
public class DealSina implements DealStrategy{
@override
public void dealMythod(String option){
//...
}
}

//定义具体的策略2
public class DealWeChat implements DealStrategy{
@override
public void dealMythod(String option){
//...
}
}

//定义上下文,负责使用DealStrategy角色
public static class DealContext{
private String type;
private DealStrategy deal;
public DealContext(String type,DealStrategy deal){
this.type = type;
this.deal = deal;
}
public DealStrategy getDeal(){
return deal;
}
public boolean options(String type){
return this.type.equals(type);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void Share{
private static List<DealContext> algs = new ArrayList();
//静态代码块,先加载所有的策略
static {
algs.add(new DealContext("Sina",new DealSina()));
algs.add(new DealContext("WeChat",new DealWeChat()));
}
public void shareOptions(String type){
DealStrategy dealStrategy = null;
for (DealContext deal : algs) {
if (deal.options(type)) {
dealStrategy = deal.getDeal();
break;
}
}
dealStrategy.dealMythod(type);
}
}

再回忆一下策略模式中的各个角色,代码中的DealStrategy接口就是策略,DealSinaDealWeChat是具体的策略,DealContext就是使用策略的上下文。

所以这样的代码已经符合策略模式的代码结构了。我们通过策略模式将策略的定义、创建、使用解耦,让每一部分都不至于太复杂,也去除了if...else这样的条件判断语句,代码的可维护性和可拓展性都提高了。

我们把可变的部分放到了Share 类中的静态代码段中。如果有新的需求,要添加一个分享的方式时,只需要定义好具体的策略,然后修改 Share 类中的静态代码段,其他代码都不需要修改。

优点

  • 算法可以自由切换
  • 避免使用多重条件判断
  • 扩展性良好。

缺点

  • 策略类会增多
  • 所有策略类都需要对外暴露。

使用场景

  • 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  • 一个系统需要动态地在几种算法中选择一种。
  • 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

请我喝杯咖啡吧~