行为模式---策略模式和状态模式

策略模式

策略模式类图:
这里写图片描述

策略模式重在抽象行为,即将行为抽象为具体的类,调用的时候动态选择行为,策略模式不同策略之间可以相互替换,并不影响最终结果,比如定义不同算法,不同算法之间虽然逻辑不同,但要求执行结果一样,所以策略模式多用于封装算法

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.ConcreteStateA
strategy.ConcreteStateB
strategy.ConcreteStateC
strategy.ConcreteStateA

策略模式和状态模式对比

不同点

  • 策略模式
    重行为,轻数据,抽象行为,所有接口抽象都可以认为是策略模式的变种,要求策略之间平等,可以相互替换,使用端必须了解不同策略之间的区别,才可以选择正确的行为;策略模式多用于算法替换

  • 状态模式
    重数据,轻行为,各个状态之间可以相互流转,各个状态之间不平等,不能相互替换,使用端不需要了解对象各个状态可以正确使用对象(此处有些线程各个状态间切换的感觉);状态模式可以实现状态机

相同点:
都是对类的某一点进行抽象(策略模式主要是方法,状态模式主要是数据),类图相似,都容易造成类泛滥,个人觉得外部状态的状态模式其实就是策略模式,策略模式的范围应该比状态模式要大

猜你喜欢

转载自blog.csdn.net/weixin_43060721/article/details/82118435