java 决策者模式_java设计模式之策略模式

策略模式的定义:

策略模式又叫政策模式,它将定义的算法族分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户,属于行为型设计模式。

很多同学可能不太理解这个定义,我举个简单的例子,比如客户要实现一个功能,分为A,B,C,D4个步骤完成,其中A和C步骤是很容易发生改变的,所以我们将A和C步骤分别封装起来,

具体实现方式是将A和C定义为接口,各自分别有1,2,3种实现方式。此时A和C对应的就是算法族,各自的实现叫做算法,各个算法之间可以相互替换,来达到不同的实现目的。客户

需要实现的功能可以由A和C算法族组合实现各式各样不同的功能,而我们实现功能的主干永远不会改变。

策略模式的使用就是面向对象的继承和多肽机制,从而实现同一行为在不同场景下具备不同的功能实现。

策略模式的UML类图:

3db032f4e7f4c64a250e4d53fe9ea803.png

由上图可以看到,策略模式主要包含3个角色。

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

抽象策略角色(IStrategy):规定策略和算法的行为。

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

注意:策略模式中的上下文角色(Context),其职责是隔离客户端与策略类的耦合,让客户端完全与上下文角色沟通,不需要关心具体策略。

Context类在具体的开发中实现可以有多种方法,比如接下来的实例中就是通过枚举类是实现的。

策略模式实现场景:

这里举一个简单的小例子,比如某明显开一场演唱会,后台调音师需要根据明星演唱的歌曲准备背景音乐。这里就可以运用策略模式去实现。

1,先定义一个背景音乐的接口,创建一个播放的方法。

package strategy;

/**

* @ClassName BackgroundMusic

* @Description 背景音乐接口

* @Author liuyi

* @Date 2020/6/14 11:08

* @Version 1.0

*/

public interface BackgroundMusic {

/**

* @Author liuyi

* @Description 定义播放的方法

* @Date 11:10 2020/6/14

* @Param []

* @return void

**/

public void play();

}

2,分别有三种背景音乐去实现该接口

背景音乐1

package strategy;

/**

* @ClassName BackgroundMusic1

* @Description TODO

* @Author liuyi

* @Date 2020/6/14 11:12

* @Version 1.0

*/

public class BackgroundMusic1 implements BackgroundMusic {

@Override

public void play() {

System.out.println("开始播放背景音乐1");

}

}

背景音乐2

package strategy;

/**

* @ClassName BackgroundMusic2

* @Description TODO

* @Author liuyi

* @Date 2020/6/14 11:13

* @Version 1.0

*/

public class BackgroundMusic2 implements BackgroundMusic{

@Override

public void play() {

System.out.println("开始播放背景音乐2");

}

}

背景音乐3

package strategy;

/**

* @ClassName BackgroundMusic3

* @Description TODO

* @Author liuyi

* @Date 2020/6/14 11:13

* @Version 1.0

*/

public class BackgroundMusic3 implements BackgroundMusic {

@Override

public void play() {

System.out.println("开始播放背景音乐3");

}

}

3,创建背景音乐编号枚举类

package strategy;

/**

* @ClassName MusicNumEnum

* @Description 背景音乐编号枚举类

* @Author liuyi

* @Date 2020/6/14 11:20

* @Version 1.0

*/

public enum MusicNumEnum {

music1(1,"strategy.BackgroundMusic1"),

music2(2,"strategy.BackgroundMusic2"),

music3(3,"strategy.BackgroundMusic3");

MusicNumEnum(int num, String className){

this.num = num;

this.className = className;

}

//编号

private int num;

//类名称

private String className;

public int getNum() {

return num;

}

public void setNum(int num) {

this.num = num;

}

public String getClassName() {

return className;

}

public void setClassName(String className) {

this.className = className;

}

//根据num获取className

public static String getClassNameByNum(int num){

MusicNumEnum[] values = MusicNumEnum.values();

for (MusicNumEnum value : values) {

if(value.getNum()==num){

return value.getClassName();

}

}

return null;

}

}

4,测试

package strategy;

/**

* @ClassName StrategyTest

* @Description 策略模式测试类

* @Author liuyi

* @Date 2020/6/14 11:16

* @Version 1.0

*/

public class StrategyTest {

public static void main(String[] args) throws Exception {

palyByNum(1);

palyByNum(3);

palyByNum(2);

}

/**

* @Author liuyi

* @Description 根据播放编号播放对应的背景音乐

* @Date 11:41 2020/6/14

* @Param [num]

* @return void

**/

public static void palyByNum(int num) throws Exception{

//根据背景音乐编号播放对应的背景音乐

BackgroundMusic backgroundMusic = (BackgroundMusic)(Class.forName(MusicNumEnum.getClassNameByNum(num)).newInstance());

backgroundMusic.play();

}

}

从代码可以看出我们需要播放某个音乐,只需要传入对应的编号即可,不需要对主干代码进行修改。如果下场演唱会需要新增背景音乐,则添加一个背景音乐类,然后在枚举类配置对应的编号和类的关系即可。

从策略模式的概念来看,每一种背景音乐其实就是一种具体的算法,背景音乐1,背景音乐2,背景音乐3它们之间可以互相替换,来达到不同的目的,而使用的客户是不需要知道这些的存在的, 用户只需要传入算法

对应的编号或者类型即可。

策略模式的优点:

策略模式符合开闭原则。

策略模式避免了多重条件转移语句,如if...else语句、switch...case语句。

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

策略模式的缺点:

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值