策略模式是面向对象行为模式中的一种简单常用的设计模式。 首先看下GOF对策略模式的定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。 策略模式的应用场景描述: (1)实现某特定功能在不同的情况下采用不同的策略即算法,程序在运行时动态选择所要采用的策略。 (2)对客户端完全隐藏算法的具体实现细节。 (3)不同种算法之间可以彼此替换且完全独立。 策略模式的三种角色: (1)抽象策略角色:通常由一个接口或者抽象类实现。 (2)具体策略角色:即包含具体策略的实现算法的类,程序中可能不止一个具体策略的角色,多个角色彼此独立。具体策略角色实现了抽象策略角色接口。 (3)环境角色:包含一个抽象策略角色的引用,通过set方法或构造方法完成策略对象的赋值,并提供给客户端一个策略调用的方法。
下面以超市打折促销的例子为大家描述下策略模式的具体使用方法。 超市打折促销有以下几种方式: (1)对普通会员是商品原价。 (2)对中级会员是商品原价的85折。 (3)对高级会员是商品原价的75折。
了解了功能需求之后,用策略模式如何实现功能呢?下面给大家贴上范例代码。 1、第一个文件:价格计算抽象策略接口(ICalculationPriceStrategy.java)
点击(此处)折叠或打开
/** * 价格计算策略接口 * */ public interface ICalculationPriceStrategy { /** * 价格计算方法 * @return */ public double calculationPrice(double price); } 2、第二个文件:普通会员价格计算的策略实现类(OrdinaryMemberStrategy.java)点击(此处)折叠或打开
/** * 普通会员价格计算策略实现类 */ public class OrdinaryMemberStrategy implements ICalculationPriceStrategy { @Override public double calculationPrice(double price) { System.out.println("--采用普通会员价格计算策略--"); return price; } } 3、第三个文件:中级会员价格计算的策略实现类(IntermediateMemberStrategy.java)点击(此处)折叠或打开
/** * 中级会员价格计算策略实现类 */ public class IntermediateMemberStrategy implements ICalculationPriceStrategy { @Override public double calculationPrice(double price) { System.out.println("--采用中级会员价格计算策略--"); return price * 0.85; } } 4、第四个文件:高级会员价格计算的策略实现类(SeniorMemberStrategy.java)点击(此处)折叠或打开
/** * 高级会员价格计算策略实现类 */ public class SeniorMemberStrategy implements ICalculationPriceStrategy { @Override public double calculationPrice(double price) { System.out.println("--采用高级会员价格计算策略--"); return price * 0.75; } } 5、第五个文件:环境角色(CalcPriceContext.java)点击(此处)折叠或打开
/** * 价格计算环境角色对象 */ public class CalcPriceContext { private ICalculationPriceStrategy calcPriceStrategy; public CalcPriceContext(ICalculationPriceStrategy calcPriceStrategy){ this.calcPriceStrategy = calcPriceStrategy; } public double calculationPrice(double price){ double finalPrice = 0; if(calcPriceStrategy != null){ finalPrice = calcPriceStrategy.calculationPrice(price); } return finalPrice; } } 6、第六个文件:客户端测试方法(TestMain.java)点击(此处)折叠或打开
public class TestMain { public static void main(String [] args){ double price = 368; double finalPrice = 0; CalcPriceContext context = null; context = new CalcPriceContext(new OrdinaryMemberStrategy()); finalPrice = context.calculationPrice(price); System.out.println("普通会员价格为:" + finalPrice); context = new CalcPriceContext(new IntermediateMemberStrategy()); finalPrice = context.calculationPrice(price); System.out.println("中级会员价格为:" + finalPrice); context = new CalcPriceContext(new SeniorMemberStrategy()); finalPrice = context.calculationPrice(price); System.out.println("高级会员价格为:" + finalPrice); } } 看了上面的策略模式实现,让我们分析下策略模式的优点,首先考虑个问题如果以上功能不用策略模式实现,那我们的代码会是什么样子的呢?点击(此处)折叠或打开
public class CalcPriceMain { public static void main(String [] args){ double price = 368; double finalPrice = 0; CalcPriceMain calcPriceMain = new CalcPriceMain(); finalPrice = calcPriceMain.calculationPrice("ordinary",price); System.out.println("普通会员价格为:" + finalPrice); finalPrice = calcPriceMain.calculationPrice("intermediate",price); System.out.println("中级会员价格为:" + finalPrice); finalPrice = calcPriceMain.calculationPrice("senior",price); System.out.println("高级会员价格为:" + finalPrice); } /** * 价格计算逻辑处理 * @param memberType * @param price * @return */ public double calculationPrice(String memberType,double price){ if("ordinary".equals(memberType)){ return calcPriceForOrdinaryMember(price); }else if("intermediate".equals(memberType)){ return calcPriceForIntermediateMember(price); }else if("senior".equals(memberType)){ return calcPriceForSeniorMember(price); } return 0; } /** * 普通会员价格计算实现方法 * @param price * @return */ public double calcPriceForOrdinaryMember(double price){ return price; } /** * 中级会员价格计算实现方法 * @param price * @return */ public double calcPriceForIntermediateMember(double price){ return price * 0.85; } /** * 高级会员价格计算实现方法 * @param price * @return */ public double calcPriceForSeniorMember(double price){ return price * 0.75; } }代码对比可以知道传统的实现方式,将各种策略的实现全都耦合在一起非常不利于代码的扩展,如果要额外新增新的策略,则要更改现在的代码结构违背了程序设计的开闭原则。 策略模式的优点如下: (1)策略模式提供了管理相关的算法族的方法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。 (2)使用策略模式可以避免使用多重条件Context对象。这本身没有解除客户端需要选择判断的压力,而策略Context来承担,这就最大化的减轻了客户端的压力。