设计模式-策略模式

模式定义

定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。

主要作用(解决的问题)

将算法的责任和本身进行解耦,使得:

  1. 算法可独立于使用外部而变化。
  2. 客户端方便根据外部条件选择不同策略来解决不同问题。

模式原理

UML类图

策略模式

模式优点

  1. 策略类之间可以自由切换
    由于策略类都实现同一个接口,所以使它们之间可以自由切换。
  2. 易于扩展
    增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“。
  3. 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

模式缺点

  1. 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  2. 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

应用场景

  1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

  2. 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。

  3. 一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端涉及到不必要接触到的复杂的和只与算法有关的数据。

  4. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。

模式示例

示例背景

背景:假设有一家百货公司,最近在定年度的促销活动
冲突:每个节日用同一个促销活动太枯燥,没吸引力
解决方案:针对不同节目使用不同促销活动进行促销

使用步骤

定义抽象策略角色(Strategy)

百货公司所有促销活动的共同接口

1
2
3
4
5
6
7
8
9
10
11
12
package main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 定义抽象策略角色:百货公司所有促销活动的共同接口
*/
public abstract class Strategy {
/**
* 活动展示
*/
public abstract void show();
}

定义具体策略角色(Concrete Strategy)

春节促销活动

1
2
3
4
5
6
7
8
9
10
11
12
13
package main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 定义具体策略角色:春节促销活动
*/
public class StrategyA extends Strategy {

@Override
public void show() {
System.out.println("为春节准备的促销活动A");
}
}

中秋促销活动

1
2
3
4
5
6
7
8
9
10
11
12
13
package main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 定义具体策略角色:中秋促销活动
*/
public class StrategyB extends Strategy {

@Override
public void show() {
System.out.println("为中秋节准备的促销活动B");
}
}

圣诞促销活动

1
2
3
4
5
6
7
8
9
10
11
12
13
package main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 定义策略角色:圣诞促销活动
*/
public class StrategyC extends Strategy {

@Override
public void show() {
System.out.println("为圣诞节准备的促销活动C");
}
}

定义环境角色(Context)

用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员

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 main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 定义环境角色:用于连接上下文,把促销活动推销给用户,这里可以理解为销售员
*/
public class SalesMan {
//持有抽象策略角色的引用
private Strategy strategy;

/**
* 生成销售员实例时告诉销售员什么节日(构造方法)
* 使得让销售员根据传入的参数(节日)选择促销活动(这里使用一个简单的工厂模式)
*/
public SalesMan(String festival) {
switch (festival) {
//春节就使用春节促销活动
case "A":
strategy = new StrategyA();
break;
//中秋节就使用中秋节促销活动
case "B":
strategy = new StrategyB();
break;
//圣诞节就使用圣诞节促销活动
case "C":
strategy = new StrategyC();
break;
}
}

/**
* 向客户展示促销活动
*/
public void salesManShow() {
strategy.show();
}
}

客户端调用

让销售员进行促销活动的落地

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
package main.java.com.study.designPatterns.strategy.demoOne;

/**
* @author: whb
* @description: 客户端调用
*/
public class Client {
public static void main(String[] args) {
SalesMan mSalesMan;

//春节来了,使用春节促销活动
System.out.println("对于春节:");
mSalesMan = new SalesMan("A");
mSalesMan.salesManShow();


//中秋节来了,使用中秋节促销活动
System.out.println("对于中秋节:");
mSalesMan = new SalesMan("B");
mSalesMan.salesManShow();

//圣诞节来了,使用圣诞节促销活动
System.out.println("对于圣诞节:");
mSalesMan = new SalesMan("C");
mSalesMan.salesManShow();
}
}

本文标题:设计模式-策略模式

文章作者:王洪博

发布时间:2018年10月03日 - 20:10

最后更新:2020年02月17日 - 09:02

原始链接:http://whb1990.github.io/posts/ea641220.html

▄︻┻═┳一如果你喜欢这篇文章,请点击下方"打赏"按钮请我喝杯 ☕
0%