Java策略模式(Strategy)

一、概述
     策略模式定义一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换,而且使这些算法在客户端调用它们的时候能够互不影响地变化。策略模式属于对象行为型模式,它们之间是弱连接的关系,提高了软件的可扩展性与可重用性。策略模式适用于当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。
     策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。策略模式一个很大的特点就是各个策略算法的平等性。一系列具体的策略算法的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。

二、策略模式的结构


      抽象策略角色:该类中实现了对抽象策略中定义的接口或者抽象类的引用;
      环境角色:这是一个抽象角色,此角色给出所有的具体策略类所需的接口,它可由接口或抽象类来实现;
      具体策略角色:它封装了实现同不功能的不同算法,可能不止一个具体策略角色。
三、策略模式的步骤
      策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以互相替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开来,算法的修改不会影响环境和客户端。
     1)对策略角色定义一个公共接口,即对一组算法抽象出一个共同接口,定义这个共同接口;
     2)编写策略类,该类实现了上面的公共接口,每个策略类都有其独特的实现;
     3)编写环境角色类,类中持有一个对共同策略接口的引用,对策略对象注入如set方法和get方法或者用构造方法完成赋值。

四、程序实例

//一个策略算法接口
public interface Strategy {
	// 策略方法
	public int calculate(int a, int b);
}
//一个加法策略类,实现策略接口 
public class AddCalculate implements Strategy {
	@Override
	public int calculate(int a, int b) {
		System.out.println("调用AddCalculate执行的加法运算");
		return a + b;
	}
}
//一个减法策略类,实现策略接口 
public class SubtractStrategy implements Strategy {
	@Override
	public int calculate(int a, int b) {
		System.out.println("调用SubtractStrategy执行的减法运算");
		return a - b;
	}
}
//一个环境角色类,持有对策略接口的引用
public class Context {
	private Strategy strategy;

	// 获得策略类对象
	public Strategy getStrategy() {
		return strategy;
	}

	// 用set方法注入策略对象
	public void setStrategy(Strategy strategy) {
		this.strategy = strategy;
	}

	// 环境角色中的接口方法,其具体结果依赖于策略引用指向的具体策略角色对象
	public int calculate(int a, int b) {
		return this.strategy.calculate(a, b);
	}
}
public class Client {
	public static void main(String[] args) {
		Context context = new Context();
		Strategy addStrategy = new AddCalculate();
		context.setStrategy(addStrategy);
		System.out.println(context.calculate(3, 4));
		System.out.println("===========================");
		Strategy subtractStrategy = new SubtractStrategy();
		context.setStrategy(subtractStrategy);
		System.out.println(context.calculate(8, 2));
	}
}
调用AddCalculate执行的加法运算
7
==================================
调用SubtractStrategy执行的减法运算
6

五、策略模式的优缺点
优点:
(1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。(2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。
缺点: (1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。(2)由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。

六、策略模式与状态模式的比较
     1)
通俗地讲,二者之间的区别在于状态模式在集体作战,而策略模式是单兵作战。状态模式因为其内部状态的改变会有不同的行为出现,而对于策略模式,只要客户端选中了一种策略,在整个生命周期内,都是这种策略。所以,在区分使用状态模式和策略模式的时候,主要是看系统有没有状态的变化,如果系统在整个生命周期内,只有一种状态,选择策略模式;如果系统在整个过程中,状态多样性,那需要选择状态模式。
     2)状态模式的结构和策略模式的结构类似,但是它们的目的、实现、本质却是完全不一样的。行为之间的特性也是状态模式和策略模式一个很重要的区别,状态模式的行为是平行性的,不可相互替换的;而策略模式的行为是平等性的,是可以相互替换的。
     3)使用场景
      状态模式:当对象的行为随对象的状态的改变而改变时,我们为了解耦多重判断条件,封装行为的变化,可以定义一个抽象的状态类,提供对象行为接口。具体与状态相关的行为,由它的子类去实现。
      策略模式:“策略”二字等同于算法,当现实系统中需要对算法动态指定,并且可以互相替换,可以抽象出算法的调用接口,具体的算法实现由具体的策略角色去实现,根据里氏替换原则,任何出现父类的地方都可以使用它的子类去替换,这样符合我们的业务需求。
     虽然两者都是抽象出父类规范调用接口,具体的行为由子类实现,环境对象同时包含父类的引用,但是这两者模式应用的场景完全不同。例如:你去ATM机取款,如果你的账户处于冻结状态,就不能正常取款。这里你的银行账户至少有两个状态就是冻结与非冻结,这样的业务解决方案你应该不会想到用策略模式去解决。又如商场打折,有很多打折的策略,儿童用品打7折,老人用品打5折,这个问题不会跟状态模式扯上关系吧,这里商品你不能说有老人状态和儿童状态。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值