alexpdh's blog

Java设计模式(二):策略模式

策略模式(strategy pattern)

策略模式(strategy pattern):属于对象的行为模式。策略模式定义了一系列的算法,并将每个算法封装起来,让他们之间可以相互转换,该模式让算法的变化,不会影响到使用算法的客户。


策略模式UML图

策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:准备一组算法,并将每一个算法封装起来,使得它们可以互换。

策略模式


策略模式涉及到的三个角色:

环境(Context)角色:该角色中实现了对抽象策略中定义的接口或者抽象类的引用。
抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。


策略模式的意义:

从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合,低耦合的特性使软件具有更强的可扩展性,易于维护;更重要的是,它大大提高了软件的可重用性。


示例代码

抽象策略接口 Strategy

1
2
3
4
5
6
7
8
9
10
11
12
package com.example.strategyPattern;
/**
* 策略模式:抽象策略类
* Created by Administrator on 2017/3/30.
*/
public interface Strategy {
/**
* 算法方法
*/
public void algorithmInterface();
}

具体算法类A ConcreteStrategyA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.strategyPattern;
/**
* 策略模式:具体算法A
*
* @author pengdh
* @date: 2017-03-30 23:28
*/
public class ConcreteStrategyA implements Strategy {
@Override
public void algorithmInterface() {
System.out.println("算法A实现");
}
}

具体算法类B ConcreteStrategyB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.strategyPattern;
/**
* 策略模式:具体算法B
*
* @author pengdh
* @date: 2017-03-30 23:31
*/
public class ConcreteStrategyB implements Strategy {
@Override
public void algorithmInterface() {
System.out.println("算法B实现");
}
}

具体算法类C ConcreteStrategyC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.strategyPattern;
/**
* 策略模式:具体算法C
*
* @author pengdh
* @date: 2017-03-30 23:32
*/
public class ConcreteStrategyC implements Strategy {
@Override
public void algorithmInterface() {
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
package com.example.strategyPattern;
/**
* 环境角色类
*
* @author pengdh
* @date: 2017-03-30 23:34
*/
public class Context {
// 申明一个抽象的策略对象
private Strategy strategy;
// 构造函数,传入一个具体的策略对象
public Context(Strategy strategy) {
this.strategy = strategy;
}
/**
* 策略方法
*/
public void contextInterface() {
strategy.algorithmInterface();
}
}

客户端测试类 TestStrategyPattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.example.strategyPattern;
/**
* 策略模式测试类
*
* @author pengdh
* @date: 2017-03-30 23:39
*/
public class TestStrategyPattern {
public static void main(String[] args) {
Context context;
context = new Context(new ConcreteStrategyA());
context.contextInterface();
context = new Context(new ConcreteStrategyB());
context.contextInterface();
context = new Context(new ConcreteStrategyC());
context.contextInterface();
}
}

策略模式的使用场景

例如超市或者商场会不定期的搞一些促销活动,活动分为多种形式,如针对不同商品的折扣力度不一样,有的打八折,有的五折;另外一些又使用满减的方式,如满300减100。而且这类的促销活动每次都不是固定的。针对这种场景我们就可以使用策略模式。

  • 策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。

策略模式的优点

(1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。

(2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。


策略模式的缺点

(1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。

(2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。


参考文献

alexpdh wechat
欢迎扫一扫关注 程序猿pdh 公众号!