策略模式(Strategy Pattern)属于对象行为模式。其作用是针对一组算法,将每个算法封装到具有共同接口的独立类中,从而使它们可以相互替换。
策略模式的意图是将可以互换的方法封装在各自的对立类中并且让每个方法都实现一个共同的接口。
策略模式(Strategy pattern)中涉及到三个角色:
- 环境(Context)角色:持有一个Strategy类的引用的类
- 抽象策略(Abstract Strategy)角色:这是一个抽象角色,通常由一个接口或者抽象类实现,此角色定义了所有具体策略对象所需要的接口。
- 具体策略(Concrete Strategy)角色:包装了相关算法的或行为的具体实现类。
有这样一个需要,在一个项目中,如果用户的认证情况不符合要求需要发送消息提醒用户需要在多长时间内完成认证。在最后今天需要每天发送一次提醒,而有的消息不是那么紧急值需要每周发送一次。还有一些特殊场景需要个性化定制。
这样我们可以通过策略模式实现。
/** * * @author zhangwei_david * @version $Id: SendStrategy.java, v 0.1 2014年11月6日 下午8:49:09 zhangwei_david Exp $ */ public interface SendStrategy { public boolean send(Message msg); } /** * * @author zhangwei_david * @version $Id: OnceAweek.java, v 0.1 2014年11月6日 下午9:04:59 zhangwei_david Exp $ */ public class OnceAweek implements SendStrategy { /** * @see com.cathy.demo.pattern.strategy.SendStrategy#send(com.cathy.demo.pattern.strategy.Message) */ public boolean send(Message msg) { System.out.println("每周一次"); return true; } } /** * 每天一次 * @author zhangwei_david * @version $Id: OnceADay.java, v 0.1 2014年11月6日 下午8:53:07 zhangwei_david Exp $ */ public class OnceADay implements SendStrategy { /** * @see com.cathy.demo.pattern.strategy.SendStrategy#send(com.cathy.demo.pattern.strategy.Message) */ public boolean send(Message msg) { System.out.println("每天一次"); return true; } } /** * * @author zhangwei_david * @version $Id: Message.java, v 0.1 2014年11月6日 下午8:50:45 zhangwei_david Exp $ */ public class Message { } /** * * @author zhangwei_david * @version $Id: SmsSender.java, v 0.1 2014年11月6日 下午8:55:18 zhangwei_david Exp $ */ public class SmsSender { private SendStrategy sendStrategy; public SmsSender(SendStrategy sendStrategy) { super(); this.sendStrategy = sendStrategy; } /** * 发送消息 * * @param msg */ public void sendSMS(Message msg) { sendStrategy.send(msg); } } /** * * @author zhangwei_david * @version $Id: Clinet.java, v 0.1 2014年11月6日 下午9:05:36 zhangwei_david Exp $ */ public class Clinet { /** * * @param args */ public static void main(String[] args) { new SmsSender(new OnceADay()).sendSMS(new Message()); new SmsSender(new OnceAweek()).sendSMS(new Message()); new SmsSender(new SendStrategy() { public boolean send(Message msg) { System.out.println("一天两次"); // return true; } }).sendSMS(new Message()); } }
策略模式有很多优点同样也有缺点。
优点有:
- 策略模式提供了管理相关算法簇的办法。策略的等级结构定义了一个算法或行为族。恰当的使用集成可可以把公共的代码移动到父类里,从而避免代码的重复。
- 策略模式提供了可怀疑替换继承关系的办法。继承可以处理多种算法或行为。
- 使用策略模式可以避免使用多重条件转移语句。
缺点:
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略。
- 策略模式造成了很多策略类。
策略模式(Strategy Pattern)和 状态模式(State Pattern)的比较:
策略模式(Stategy Pattern)和状态模式(State Pattern)的结构几乎一摸一样。但是策略模式和状态模式却是完全不同的两种思想。 状态模式注重的是状态的迁移,而策略模式不是这样;策略模式允许客户端定制策略,而状态模式却很少这样设计,因为状态一般是固定的。
策略模式(Strategy Pattern)和模板方法(Template Method Pattern)比较:
从结构上讲策略模式(Strategy Pattern)的抽象策略通常是定义为接口,而模板方法模式(Template Method Pattern)则通常定义为抽象类。虽然二者都可以看做是对算法或者策略的抽象,但是模板方法模式(Template Method Pattern)通常定义后一个策略的框架,子类实现的通常都是策略的一部分;而策略模式(Strategy Pattern)则是对算法整体进行抽象。