走进设计模式的世界10:蹭一波双11热度-状态模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35165632/article/details/84063341

状态模式 :

允许对象在内部状态改变时,改变他的行为,对象看起来好像是修改了他的类。

解释:状态模式允许一个对象基于内部状态而拥有不同的行为。和程序状态机不同,状态模式用类代表状态。Context会将内容委托给当前状态对象。通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。状态模式和策略模式有相同的类图,但是他们的意图不同。策略模式通常会用行为或算法配置context类,状态转换state是由context控制的。使用状态模式通常会导致设计类中的类数目增加。状态类可以被多个context实例共享。

状态模式样例演示:蹭一波双11热度,来说订单。

/**
    抛开电商不说,但从一个寒酸的小商城的订单系统来说,
    他们的设计特别的繁琐,通过一系列复杂的状态来控制订单的行为
    以及客户的行为。
**/

public class Loan{
    
    // 待付款
    final static int DaiFuKuan = 0;
    // 待发货
    final static int DaiFaHuo = 2;
    // 已发货
    final static int YiFaHuo = 3;
    // 已收货
    final static int YiShouHuo = 4;
    // 交易完成
    final static int JiaoYiWanCheng = 5;
    // 订单状态
    private int loanState;
   
    public Loan(){
        // 默认订单创建了状态为待付款
        loanState = DaiFuKuan;
    }
    
    // 付款
    public void fuKuan(){
        if(DaiFuKuan==state){
           System.out.println("付款成功!"); 
        }else if(DaiFaHuo==state){
           System.out.println("已经付款过,无需再次付款!");
        }else if(YiFaHuo ==state){
           System.out.println("已经发货,无需再次付款!");
        }else if(YiShouHuo==state){
           System.out.println("已经收货,无需再次付款!");
        }else{
           System.out.println("交易完成,无需再次付款!");
        }            
    }

    // 催促卖家发货
    public void faHuo(){
        if(DaiFuKuan==state){
           System.out.println("您现在还未付款,无法督促卖家发货!"); 
        }else if(DaiFaHuo==state){
           System.out.println("催促发货成功!");
        }else if(YiFaHuo ==state){
           System.out.println("已经发货,无需催促!");
        }else if(YiShouHuo==state){
           System.out.println("已经收货,无需催促!");
        }else{
           System.out.println("交易完成,无需催促!");
        }     
    }
    
    // 收货
    public void shouHuo(){
        if(DaiFuKuan==state){
           System.out.println("您现在还未付款,无法收货!"); 
        }else if(DaiFaHuo==state){
           System.out.println("货物未到达无法收货!");
        }else if(YiFaHuo ==state){
           System.out.println("货物未到达无法收货!");
        }else if(YiShouHuo==state){
           System.out.println("收货成功!");
        }else{
           System.out.println("交易完成,无法再次收货!");
        }   
    }

    
}

就这样看似完美严谨的一个订单就被设计好了,但是,如果现在需要增加退款的请求呢???当然我们依然可以严谨的把退款的逻辑写的很好,但是呢?为什么我们不选择一个捷径呢,那么我们就来看下面的设计。

public class LoanContext{
    // 待付款状态
    private LoanState daiFuKuanState;
    // 待发货状态
    private LoanState daiFaHuoState;
    // 已发货状态
    private LoanState yiFaHuoState;
    // 已收货状态
    private LoanState yiShouHuoState;
    // 交易完成状态
    private LoanState jiaoYiWanChengState;
    // 已退款状态
    private LoanState yiTuiKuanState;
    
    // 当前订单状态
    private LoanState state;
    
    public LoanContext(){
        // 把本对象的引用交给状态
        daiFuKuanState = new DaiFuKuanState(this);
        daiFaHuoState = new DaiFaHuoState(this);
        yiFaHuoState = new YiFaHuoState(this);
        yiShouHuoState = new YiShouHuoState(this);
        jiaoYiWanChengState = new JiaoYiWanChengState(this);
        yiTuiKuanState = new YiTuiKuanState(this);
        // 默认状态为 待付款
        state = daiFuKuanState;
    }

    // 收货
    public void shouHuo(){
        state.shouHuo();
    }
    // 发货
    public void faHuo(){
        state.fahuo();
    }
    // 付款
    public void fuKuan(){
        state.fuKuan();
    }
    // 退货
    public void tuiHuo(){
        state.tuiHuo();
    }
    
}

这样订单的处理类就完成了,然后整理下各个订单的信息

// 订单状态抽象类
public Abstract class LoanState{
    private LoanContext context;

    public LoanState (LoanContext context){
        this.context = context;
    }
    
    public void shouHuo();
    
    public void faHuo();
    
    public void fuKuan();
    
    public void tuiHuo();
}

/**
    待付款状态
**/
public class DaiFuKuanState extends LoanState{
    // 收货
    public void shouHuo(){
        System.out.println("您未付款,无法收货");
    }

    // 付款
    public void fuKuan(){
        System.out.println("付款成功!");
        // 设置状态为待发货。
        context.setState(context.getDaiFaHuo());
    }

    // 发货
    public void faHuo(){
        System.out.println("您未付款,无法发货!");
    }
    
    // 收货
    public void shouHuo(){
        System.out.println("您未付款,无法收货!");
    }

    // 退款
    public void tuiKuan(){
        System.out.println("您未付款,无法退款!");
    }
}

/**
    待发货状态
**/
public class DaiFaHuoState extends LoanState{
     // 收货
    public void shouHuo(){
        System.out.println("货未发出无法收货,无法收货");
    }

    // 付款
    public void fuKuan(){
        System.out.println("已经付款,无法二次付款!");
    }

    // 发货
    public void faHuo(){
        System.out.println("催促发货成功!卖家已发货!");
        context.setState(context.yiFaHuo());
    }
    
    // 收货
    public void shouHuo(){
        System.out.println("货物未到!");
    }

    // 退款
    public void tuiKuan(){
        System.out.println("货物已发无法退款!");
    }
}

按照这种方式继续对其他类进行修改之后,一个完整的订单系统就完成了。通过context控制了订单的状态直接进行了下一步。而且增加了拓展性和可维护性!

猜你喜欢

转载自blog.csdn.net/qq_35165632/article/details/84063341