状态模式State

1.意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
2.结构
在这里插入图片描述

Context(上下文)定义客户感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态。
State(状态)定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState(具体状态子类)每个子类实现与Context的一个状态相关的行为。
3.适用性:
一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。
4.常见案例:会员等级升级
代码案例
某航空公司的会员积分系统将其会员划分为:普卡(Basic)、银卡(Silver)和金卡(Gold)三个等级。非会员(NonMember)可以申请成为普卡会员。会员的等级根据其一年内累积的里程数进行调整。描述会员等级调整的状态图如下图所示。现采用状态(State)模式实现上述场景。
在这里插入图片描述

软件设计师考试2018年下半年下午题第6题

class FrequentFlyer{
    CState state;
    double flyMiles;

    public FrequentFlyer() {
        state = new CBasic("普卡会员");
        flyMiles = 0;
        setState(state);
    }
    public void setState(CState state){
        this.state = state;
    }
    public void travel(int miles){
        double bonusMiles = state.travel(miles,this);
        flyMiles = flyMiles + bonusMiles;
    }
}
abstract class CState{
    public String name;
    public int flyMiles;
    public abstract double travel(int miles, FrequentFlyer context);
}
class CNoCustomer extends CState{//非会员
    public CNoCustomer(String name){
        this.name=name;
    }
    @Override
    public double travel(int miles, FrequentFlyer context) {
        System.out.println("Your travel will not account for points");
        return 0;//不累积里程数
    }
}
class CBasic extends CState{//普卡会员
    public CBasic(String name){
        this.name=name;
    }
    @Override
    public double travel(int miles, FrequentFlyer context) {
        if(context.flyMiles>=25000 && context.flyMiles<50000){
            context.setState(new CSilver("银卡会员"));//升级为银卡会员
        }
        if(context.flyMiles>=50000){
            context.setState(new CGold("金卡会员"));//升级为金卡会员
        }
        System.out.println("Your travel will account for points");
        return miles;
    }
}
class CSilver extends CState{//银卡会员
    public CSilver(String name){
        this.name=name;
    }
    @Override
    public double travel(int miles, FrequentFlyer context) {
        if(context.flyMiles>=50000){
            context.setState(new CGold("金卡会员"));//升级为金卡会员
        }
        if(context.flyMiles<=25000){
            context.setState(new CBasic("普卡会员"));//降级为普卡会员
        }
        System.out.println("Your travel will account for 1.25 times of points");
        return miles + 0.25*miles;//累积里程数
    }
}
class CGold extends CState{//金卡会员
    public CGold(String name){
        this.name=name;
    }
    @Override
    public double travel(int miles, FrequentFlyer context) {
        if(context.flyMiles>=25000 && context.flyMiles<50000){
            context.setState(new CSilver("银卡会员"));//降级为银卡会员
        }
        if(context.flyMiles<=25000){
            context.setState(new CBasic("普卡会员"));//降级为普卡会员
        }
        System.out.println("Your travel will account for 1.5 times of points");
        return miles + 0.5*miles;//累积里程数
    }
}
public class State {
    public static void main(String[] args) {
        FrequentFlyer frequentFlyer0 = new FrequentFlyer();//普卡
        frequentFlyer0.setState(new CNoCustomer("非会员"));
        frequentFlyer0.travel(6000);
        System.out.println("里程数:"+frequentFlyer0.flyMiles+",会员等级:"+frequentFlyer0.state.name);

        FrequentFlyer frequentFlyer = new FrequentFlyer();//普卡
        frequentFlyer.travel(26000);
        System.out.println("里程数:"+frequentFlyer.flyMiles+",会员等级:"+frequentFlyer.state.name);
        frequentFlyer.travel(26000);//累积里程数,升级成银卡
        System.out.println("里程数:"+frequentFlyer.flyMiles+",会员等级:"+frequentFlyer.state.name);
        frequentFlyer.travel(26000);//累积0.25倍里程数,升级成金卡
        System.out.println("里程数:"+frequentFlyer.flyMiles+",会员等级:"+frequentFlyer.state.name);
        frequentFlyer.travel(26000);//累积0.5倍里程数
        System.out.println("里程数:"+frequentFlyer.flyMiles+",会员等级:"+frequentFlyer.state.name);
    }
}

运行结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值