设计模式之策略模式

策略模式

策略模式

策略模式(Strategy Pattern)又叫政策模式(Policy Pattern),它是将定义的算法家族、分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户,属于行为型模式。策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。

策略模式可以解决在有多种算法相似的情况下,使用if..else或switch…case所带来的复杂性和臃肿性。在日常业务开发中,策略模式适用于以下场景:

1、针对同一类型问题,有多种处理方式,每一种都能独立解决问题;

2、算法需要自由切换的场景;

3、需要屏蔽算法规则的场景。

通用UML类图

image-20210424180522516

从UML类图中,可以看到,策略模式主要包含三种角色:

上下文角色(Context):用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化;

抽象策略角色(Strategy):规定策略或算法的行为;

具体策略角色(ConcreteStrategy):具体的策略或算法实现。

应用场景

策略模式在生活场景中应用也非常多。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。再比如我们在互联网移动支付的大背景下,每次下单后付款前,需要选择支付方式。

通用代码

抽象策略角色(Strategy)

1
2
3
4
public interface IStrategy
{
void algorithm(String str);
}

具体策略角色(ConcreteStrategy)

1
2
3
4
5
6
7
8
public class ConcreteStrategyA implements IStrategy
{
@Override
public void algorithm(String str)
{
System.out.println("ConcreteStrategyA algorithm " + str);
}
}
1
2
3
4
5
6
7
8
public class ConcreteStrategyB implements IStrategy
{
@Override
public void algorithm(String str)
{
System.out.println("ConcreteStrategyB algorithm " + str);
}
}

上下文角色(Context)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Context
{
private IStrategy iStrategy;

public Context(IStrategy iStrategy)
{
this.iStrategy = iStrategy;
}

void algorithm(String str)
{
iStrategy.algorithm(str);
}
}

测试代码

1
2
3
4
5
6
7
8
9
10
11
public class Main
{
public static void main(String[] args)
{
Context context = new Context(new ConcreteStrategyA());
context.algorithm("test");

context = new Context(new ConcreteStrategyB());
context.algorithm("test");
}
}

输出

1
2
ConcreteStrategyA algorithm test
ConcreteStrategyB algorithm test

策略模式在框架源码中的体现

JDK中一个比较常用的比较器Comparator接口我们看到的一个大家常用的compare()方法,就是一个策略抽象实现。

Spring的初始化也采用了策略模式,不同的类型的类采用不同的初始化策略。

首先有一个InstantiationStrategy接口

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface InstantiationStrategy {

Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
throws BeansException;

Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
Constructor<?> ctor, Object... args) throws BeansException;

Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
@Nullable Object factoryBean, Method factoryMethod, Object... args)
throws BeansException;

}

它下面有两种策略SimplelnstantiationStrategy和CglibSubclassinglnstantiationStrategy。

策略模式的优缺点

优点:

1、策略模式符合开闭原则。

2、避免使用多重条件转移语句,如if..e…语句、switch语句。

3、使用策略模式可以提高算法的保密性和安全性。

缺点:

1、客户端必须知道所有的策略,并且自行决定使用哪一个策略类。

2、代码中会产生非常多策略类,增加维护难度。

打赏

请我喝杯咖啡吧~

支付宝
微信