策略模式状态模式策略模式和状态模式对比
策略模式
策略模式类图:
策略模式重在抽象行为,即将行为抽象为具体的类,调用的时候动态选择行为,策略模式不同策略之间可以相互替换,并不影响最终结果,比如定义不同算法,不同算法之间虽然逻辑不同,但要求执行结果一样,所以策略模式多用于封装算法
Strategy 类,定义行为:
public interface Strategy { public void strategyInterface();}具体策略类,将行为封装为具体的类:
public class ConcreteStrategyA implements Strategy { @Override public void strategyInterface() { System.out.println(this.getClass().getName()); }}public class ConcreteStrategyB implements Strategy { @Override public void strategyInterface() { System.out.println(this.getClass().getName()); }}策略使用类,配置具体行为:
public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void contextInterface() { strategy.strategyInterface(); } public static void main(String[] args) { Context context = new Context(new ConcreteStrategyA()); context.contextInterface(); }}输出,可以进行ConcreteStrategyA和ConcreteStrategyB 直接的切换,也就是说使用端必须完全了解算法,才能选择正确的算法:
strategy.ConcreteStrategyA 状态模式状态模式类图:
状态模式重在抽象数据,即将类中的数据抽象为具体的类,调用的时候因为数据的不同而表现出不同的行为,状态模式的状态具有不可替换性,虽然大家都是状态,从逻辑上讲是相互平行的,但是不可替换
state类,定义各个状态需要实现的行为:
public abstract class State { public abstract void handle(Context context);}具体状态类,定义各个状态,并定义内部状态转移规则A-B-C,当然也可以使用外部状态,有context类直接设置,这样一来有点像策略模式,本人觉得内部状态才是真正的状态模式,内部状态需要具体状态类可以访问context对象,可以使用传入或者初始化持有的方式:
public class ConcreteStateA extends State { @Override public void handle(Context context) { System.out.println(this.getClass().getName()); // 转移状态 context.setState(new ConcreteStateB()); }}public class ConcreteStateB extends State { @Override public void handle(Context context) { System.out.println(this.getClass().getName()); // 转移状态 context.setState(new ConcreteStateC()); }}public class ConcreteStateC extends State { @Override public void handle(Context context) { System.out.println(this.getClass().getName()); // 转移状态 context.setState(new ConcreteStateA()); }}context类,最终的使用类
public class Context { private State state; public State getState() { return state; } public void setState(State state) { this.state = state; } public void handle(){ state.handle(this); } public static void main(String[] args) { Context context = new Context(); context.setState(new ConcreteStateA());//设置起始状态 context.handle(); context.handle(); context.handle(); context.handle(); }}输出,可以清晰看出内部状态之间的流转,而使用端可以不了解状态:
strategy.ConcreteStateAstrategy.ConcreteStateBstrategy.ConcreteStateCstrategy.ConcreteStateA 策略模式和状态模式对比不同点
策略模式
重行为,轻数据,抽象行为,所有接口抽象都可以认为是策略模式的变种,要求策略之间平等,可以相互替换,使用端必须了解不同策略之间的区别,才可以选择正确的行为;策略模式多用于算法替换
状态模式
重数据,轻行为,各个状态之间可以相互流转,各个状态之间不平等,不能相互替换,使用端不需要了解对象各个状态可以正确使用对象(此处有些线程各个状态间切换的感觉);状态模式可以实现状态机
相同点:
都是对类的某一点进行抽象(策略模式主要是方法,状态模式主要是数据),类图相似,都容易造成类泛滥,个人觉得外部状态的状态模式其实就是策略模式,策略模式的范围应该比状态模式要大