设计模式行为型:状态模式(StatePattern)案例2020-11

设计模式行为型:状态模式(StatePattern)案例

简介

优点:
1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点:
1、状态模式的使用必然会增加系统类和对象的个数。
2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
3、状态模式对象之间耦合度高,破坏"开闭原则"。

作者:秃头的路上
链接:https://www.jianshu.com/p/e335799a5a0b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

角色与理解
状态模式共分为三种角色:
Context(上下文环境):将自身的状态与行为分离出去,封装成状态类,持有抽象状态类的引用,根据自身属性变换更换具体状态类。
State(抽象状态类):具体状态类的抽象,可以持有上下文环境的引用来更换状态。
Concrete State(具体状态类):实现不同状态下的不同行为。
上下文环境引用抽象状态类完成行为的调用,状态类的状态变化可以有上下文环境处理,也可以由状态类处理。
状态类可以共享,像开关对象一样,可以被多个上下文环境引用。

流程图

本案例使用用户进行存取金额的行为,用户的账号状态作为展示

在这里插入图片描述

代码展示

账户类Account

package com.nj.boke.state;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * 账户
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    /**
     * 余额
     */
    private double balance;
    /**
     * 透支额度
     */
    private double amount;
    /**
     * 账户状态
     */
    private Accountstate accountstate;

    /**
     * 存钱
     */
    public void cq(double money){
        this.getAccountstate().cq(money);
    }

    /**
     * 取钱
     */
    public void qq(double money){
        this.getAccountstate().qq(money);
    }

    /**
     * 查看状态
     */
    public String getStatus(){
      return this.getAccountstate().getStatus();
    }
}

抽象类 状态

package com.nj.boke.state;

import lombok.Data;

/**
 * 账户状态抽象类
 */
@Data
public abstract class Accountstate {
    /**
     * 用户账号
     */
    protected Account account;
    private String status;

    public Accountstate (Account account){
        this.account=account;
    }
    protected Accountstate() {
    }
    /**
     * 存钱方法 完整方法:
     *     因为无论账户什么状态统一都可以进行存钱操作
     * @param money
     */
    public  void cq(double money){
        this.getAccount().setBalance(this.getAccount().getBalance()+money);
        this.changState();
    }

    /**
     * 取钱方法 
     *      根据状态不一致,取钱功能不一致
     * @param money
     */
    public  void qq(double money){
        double balance =this.getAccount().getBalance()-money;
        if (balance<-this.getAccount().getAmount()){
            System.out.println("您的额度不够");
            return;
        }
        this.getAccount().setBalance(balance);
        System.out.println("取钱成功");
        this.changState();
        System.out.println("---");
    };


    /**
     * 改变账户状态
     */
    public void changState(){
        //获取账户余额
        double balance = this.account.getBalance();
        if ( balance >=0){
            //账户正常
            this.account.setAccountstate(new NormalState(this.account));
        }else if(balance > -this.account.getAmount()){
            //账户透支中
            this.account.setAccountstate(new OverdraftState(this.account));
        }else if (balance == -this.account.getAmount()){
            //账户超过透支状态
            this.account.setAccountstate(new RestrictedState(this.account));
        }
    }
}

实现类

具体几个实现,状态有 正常/透支/限制账户


/**
 * 正常状态
 */
public class NormalState extends Accountstate{
    
    public NormalState() {
    }
    public NormalState(Account account) {
        super(account);
        super.setStatus("正常");
    }
}

------------------------------------------------------------


/**
 * 透支状态
 */
public class OverdraftState extends Accountstate{
    public OverdraftState() {
    }
    public OverdraftState(Account account) {
        super(account);
        super.setStatus("透支");
    }
}

------------------------------------------------------------


/**
 * 受限状态
 */
public class RestrictedState extends Accountstate{
    public RestrictedState() {
    }
    public RestrictedState(Account account) {
        super(account);
        super.setStatus("受限");
    }

    /**
     * 取钱受限
     * @param money
     */
    @Override
    public void qq(double money) {
        System.out.println("取钱功能受限");
        System.out.println("---");
    }
}


模拟用户操作

    public static void main(String[] args) {
        Accountstate state = new NormalState();
        //创建一个账户
        Account account=new Account(100,100,state);
        state.setAccount(account);

        int i=0;
        while (i<6){
            //用户取钱
            System.out.println("==============开始取钱============");
            account.qq(50);

            System.out.println("用户余额"+account.getBalance());
            System.out.println("用户额度"+account.getAmount());
            System.out.println("用户状态"+account.getStatus());
            i++;
        }

        while (i>0){
            //用户取钱
            System.out.println("==============开始存钱============");
            account.cq(20);

            System.out.println("用户余额"+account.getBalance());
            System.out.println("用户额度"+account.getAmount());
            System.out.println("用户状态"+account.getStatus());
            i--;
        }
    }

结果如下:

==============开始取钱============
取钱成功
---
用户余额50.0
用户额度60.0
用户状态正常
==============开始取钱============
取钱成功
---
用户余额0.0
用户额度60.0
用户状态正常
==============开始取钱============
取钱成功
---
用户余额-50.0
用户额度60.0
用户状态透支
==============开始取钱============
您的额度不够
用户余额-50.0
用户额度60.0
用户状态透支
==============开始取钱============
您的额度不够
用户余额-50.0
用户额度60.0
用户状态透支
==============开始取钱============
您的额度不够
用户余额-50.0
用户额度60.0
用户状态透支
==============开始存钱============
用户余额-30.0
用户额度60.0
用户状态透支
==============开始存钱============
用户余额-10.0
用户额度60.0
用户状态透支
==============开始存钱============
用户余额10.0
用户额度60.0
用户状态正常
==============开始存钱============
用户余额30.0
用户额度60.0
用户状态正常
==============开始存钱============
用户余额50.0
用户额度60.0
用户状态正常
==============开始存钱============
用户余额70.0
用户额度60.0
用户状态正常

Process finished with exit code 0

案例来自于:微信公众号码农架构
https://mp.weixin.qq.com/s/AOQD_nmSUPwHo2PQ0dL28Q

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值