欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java23种设计模式——状态模式

程序员文章站 2024-03-24 19:12:28
...

该系列文章为博主学习笔记,原文请参考参考文章
本文禁止转载,但是欢迎大家留言区留言交流[微笑]

状态模式是比较难得一种模式,状态模式是一种对象行为型模式。
当我们一个对象具备多种状态时,而且不同的状态针对不同的行为时,我们可以考虑在代码设计中运用该设计模式。
例如:
Java23种设计模式——状态模式

从该文字描述我们可以得出两点

1、对象的状态是根据游戏的积分来分出等级
2、不同的等级对应不同的操作

总结模(面)式(试):
状态模式将一个对象在每一个状态下的行为和状态转移语句分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。

Java23种设计模式——状态模式

其实状态模式是比较难得,直接通过代码来看结果吧,我把注解都写在代码上面了,能清晰一些:
代码:

/**
 * 规定<100积分为入门级
 * >100,<200为熟练级别
 * >200,<300为高手级别
 * >300     为骨灰级别
 * 初始为0,每次调用play方法积分增加100
 *
 * 改类类似于UML的Context类,关联了状态类CardState ,CardState是一个抽象的状态类,具体的实现交给具
 * 体状态类,规定了一些方法,根据里氏替换原则在程序运行期间指定具体的类。
 * 
 * 这里有个setState(CardState)方法,当状态发生改变的时候,通过具体状态类进行设置,具体状态类保留了 
 * 该类的引用,所以可以随时的对状态进行转换
 *
 * 同时该类还声明了CardState抽象类的所有方法,这样,对于客户端来讲,无须关心对象状态的转换以及对象所处
 * 的当前状态,无论对于何种状态的对象,客户端都可以一致处理,因为所有方法的处理最后都会交给当前状态类去
 * 处理,而在不同的状态类中声明的行为也不同,入门级没有熟练级别操作,熟练级别没有高级玩家的操作。
 */
public class CardPlay {
    private double balance = 0;//用户等级
    private CardState state;//维持一个对抽象状态对象的引用
    private String name;//用户名

    public CardPlay(String name) {
        this.name = name;
        Primary primary = new Primary(this);
        this.state = primary;

    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public CardState getState() {
        return state;
    }

    public void setState(CardState state) {
        this.state = state;
    }

    public void play() {
        System.out.println(this.name + "积分" + this.getBalance());
        state.play(); //调用状态对象的deposit()方法
        System.out.println("现在积分为" + this.balance);
        System.out.println("现在用户状态为" + this.state.getClass().getName());
        System.out.println("---------------------------------------------");
    }

    public void doubleScore() {
        System.out.println(this.name + "积分" + this.getBalance());
        state.doubleScore(); //调用状态对象的deposit()方法
        System.out.println("现在积分为" + this.balance);
        System.out.println("现在用户状态为" + this.state.getClass().getName());
        System.out.println("---------------------------------------------");
    }

    public void hangeCards() {
        state.hangeCards();
    }

    public void peekCards() {
        state.peekCards();
    }

}
/**
* 声明了一些方法,该类为抽象状态类,必须由具体状态类去继承,并重写这些方法,但是不同的子类,对应的方法
* 也不一样,例如入门级调用play之后,积分应该增加100,但是入门级调用了hangeCards()方法,因为该方法
* 不对入门级开放,所以应该提示用户暂未开放。
*/

public abstract class CardState {
    protected CardPlay cardPlay;

    //入门级开放
    public abstract void play();
    //熟练级别开放
    public abstract void doubleScore();
    //高手级别开放
    public abstract void hangeCards();
    //骨灰级别开放
    public abstract void peekCards();
}
/**
* 该类为入门级别的类,继承自状态类CardState,并重写了所有的方法,因为不同级别的行为不同,所以我们要规定
* 每种状态类都具备哪些行为。
* 在这里每次调用Primary方法会使用户的积分增加100,每次调用之后都应该判断当前的状态是否改变,因为该类
* 保留了对CardPlay类的引用,所以可以调用CardPlay类的setState()方法,对状态进行更新。
*  
* 
*/

//入门级别
public class Primary extends CardState {

    public Primary(CardPlay cardPlay) {
        this.cardPlay = cardPlay;
    }

    public Primary(CardState cardState) {
        this.cardPlay = cardState.cardPlay;
    }

    @Override
    public void play() {
        double current = cardPlay.getBalance() + 100;
        System.out.print("恭喜您!您的等级积分增加了100分  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    private void stateCheck() {
        final double balance = cardPlay.getBalance();
        if (balance >= 100 && balance <= 200) {
            //熟练级别
            cardPlay.setState(new Secondary(this));
        } else if (balance >= 200 && balance <= 300) {
            //高手级别
            cardPlay.setState(new Professional(this));
        } else if (balance >= 300) {
            //骨灰级别
            cardPlay.setState(new Final(this));
        }
    }

    @Override
    public void doubleScore() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }

    @Override
    public void hangeCards() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }

    @Override
    public void peekCards() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }
}
//高手级别
public class Professional extends CardState {

    public Professional(CardState cardState) {
        this.cardPlay = cardState.cardPlay;
    }

    @Override
    public void play() {
        double current = cardPlay.getBalance() + 100;
        System.out.print("恭喜您!您的等级积分增加了100分  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    private void stateCheck() {
        final double balance = cardPlay.getBalance();
        if (balance <100) {
            //入门级别
            cardPlay.setState(new Primary(this));
        } else if (balance >= 100 && balance <= 200) {
            //熟练级别
            cardPlay.setState(new Secondary(this));
        } else if (balance >= 300 ) {
            //骨灰级别
            cardPlay.setState(new Final(this));
        }
    }

    @Override
    public void doubleScore() {
        double current = cardPlay.getBalance() * 2;
        System.out.println("恭喜您!您的等级积分加倍了呢  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    @Override
    public void hangeCards() {
        System.out.println("使用了换牌功能,你好胖胖哦,需要我给你鼓掌么!?");
        System.out.println("---------------------------------------------");
    }

    @Override
    public void peekCards() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }
}
//熟练级别
public class Secondary extends CardState {

    public Secondary(CardState cardState){
        this.cardPlay=cardState.cardPlay;
    }

    @Override
    public void play() {
        double current = cardPlay.getBalance() + 100;
        System.out.print("恭喜您!您的等级积分增加了100分  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    private void stateCheck() {
        final double balance = cardPlay.getBalance();
        if (balance <100) {
            //入门级别
            cardPlay.setState(new Primary(this));
        } else if (balance >= 200 && balance <= 300) {
            //高手级别
            cardPlay.setState(new Professional(this));
        } else if (balance >= 300 ) {
            //骨灰级别
            cardPlay.setState(new Final(this));
        }
    }

    @Override
    public void doubleScore() {
        double current = cardPlay.getBalance() * 2;
        System.out.println("恭喜您!您的等级积分加倍了呢  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();

    }

    @Override
    public void hangeCards() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }

    @Override
    public void peekCards() {
        System.out.println("您的级别还够不能开通该权限");
        System.out.println("---------------------------------------------");
    }
}
public class Final extends CardState {

    public Final(CardState cardState) {
        this.cardPlay = cardState.cardPlay;
    }

    @Override
    public void play() {
        double current = cardPlay.getBalance() + 100;
        System.out.print("恭喜您!您的等级积分增加了100分  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    private void stateCheck() {
        final double balance = cardPlay.getBalance();
        if (balance < 100) {
            //入门级别
            cardPlay.setState(new Primary(this));
        } else if (balance >= 100 && balance <= 200) {
            //熟练级别
            cardPlay.setState(new Secondary(this));
        } else if (balance >= 200 && balance <= 300) {
            //高手级别
            cardPlay.setState(new Professional(this));
        }
    }

    @Override
    public void doubleScore() {
        double current = cardPlay.getBalance() * 2;
        System.out.println("恭喜您!您的等级积分加倍了呢  ");
        System.out.println("您当前的等级几分为: " + current);
        cardPlay.setBalance(current);
        stateCheck();
    }

    @Override
    public void hangeCards() {
        System.out.println("使用了换牌功能,你好胖胖哦,需要我给你鼓掌么!?");
        System.out.println("---------------------------------------------");
    }

    @Override
    public void peekCards() {
        System.out.println("您增加了偷看别人牌的功能,我日,提这个需求的老板不会是姓马吧,充钱才牛逼");
        System.out.println("---------------------------------------------");
    }
}
/**
* 客户端类,有没有发现客户端类很清爽,而且客户端类根本不用考虑状态的转换,直接专注于方法即可
*/
public class myClass {
    public static void main(String[] args){
        CardPlay cardPlay=new CardPlay("谢耀眼");
        cardPlay.play();
        cardPlay.doubleScore();
        cardPlay.peekCards();
        cardPlay.hangeCards();
        cardPlay.play();
        cardPlay.peekCards();
        cardPlay.doubleScore();
    }
}

输出:

Java23种设计模式——状态模式

大家可以从输出中看到,对于不同的积分,不同的具体状态类实现的行为不同,客户端只关注于方法,不用在乎状态的转换,而具体的装换的方法,封装在了具体状态类中,可以对状态转换代码进行集中管理,而不是分散在一个个业务方法中。

微信公众号:
Java23种设计模式——状态模式

QQ群:365473065