用java语言讲述设计模式---状态模式

来源:互联网 发布:手机视频短片软件 编辑:程序博客网 时间:2024/06/15 03:37

状态模式的使用场景

  • 一个对象的行为方法取决于它的状态,并且它必须在运行的时候根据状态改变为它对应的状态的行为

状态模式的重心

状态模式的重心不是如何实现各个状态对应的行为方法,而是如何组织、调用、判断这些行为方法对应状态,从而让程序结构更灵活,具有更好的维护性和扩展性。

状态模式的简单代码

/** * 同一个用户可以一直投票,但是会记录其投票总字数,不同的次数对应不同的状体,不同的状态有不同的行为 * 根据不同的投票次数,有四种结果(状态): * 正常投票:一个用户投了第一票,将该票记录到服务器 * 反复投票:一个用户投了一票后,又继续投票,提示用户不要在投票 * 恶意刷票:一个用户投票次数超过5次,根据该投票信息从服务器中删除 * 进入黑名单:一个用户投票次数超过8次,提示用户被加入了黑名单 *//** * 状态对象接口 */public interface VoteResultState {    /**     * 根据状态做不同的行为的方法,通过上面的说明我们知道需要将投票记录到服务器,所以需要投票人和投票选项,     * 服务器我们用一个Map<String,String>来代替,并且将这个服务器作为投票管理(VoteManager)的成员变量     */    void voteDetailBehavior(String voteUser, String voteOption, VoteManager voteManager);}----------------------------------------------------------------------------------------/** * 正常投票状态对象 */public class NormalVoteState implements VoteResultState {    @Override    public void voteDetailBehavior(String voteUser, String voteOption, VoteManager voteManager) {        Map<String, String> voteResultServer = voteManager.getVoteResultServer();        voteResultServer.put(voteUser, voteOption);        System.out.println("投票次数第1次,已经将投票记录到服务器中");    }}----------------------------------------------------------------------------------------/** * 重复投票状态对象 */public class RepetitionVoteState implements VoteResultState {    @Override    public void voteDetailBehavior(String voteUser, String voteOption, VoteManager voteManager) {        System.out.println("投票次数2次以上5此以下,正在重复投票,该投票不记录到服务器中");    }}----------------------------------------------------------------------------------------/** * 恶意投票状态对象 */public class SpiteVoteState implements VoteResultState {    @Override    public void voteDetailBehavior(String voteUser, String voteOption, VoteManager voteManager) {        Map<String, String> voteResultServer = voteManager.getVoteResultServer();        String remove = voteResultServer.remove(voteUser);        if (remove != null) {// 有记录可以删除            System.out.println("投票次数5次以上8此以下,正在恶意投票,所以将投票记录从服务器中删除");        } else {// 没有记录可以删除            System.out.println("投票次数5次以上8此以下,正在恶意投票");        }    }}----------------------------------------------------------------------------------------/** * 黑名单投票状态对象 */public class BlackListVoteState implements VoteResultState {    @Override    public void voteDetailBehavior(String voteUser, String voteOption, VoteManager voteManager) {        System.out.println("投票次数8次以上,用户被加入黑名单");    }}----------------------------------------------------------------------------------------/** * 该类为投票管理类,根据投票次数选择不同的状态对象调用voteDetailBehavior(),实现具体的对应状体的行为 */public class VoteManager {    //记录用户投票结果的服务器,Map<String,String>对应Map<用户名称,投票的选项>    private Map<String, String> voteResultServer = new HashMap<>();    //记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>    private Map<String, Integer> voteCountServer = new HashMap<>();    public Map<String, String> getVoteResultServer() {        return voteResultServer;    }    /**     * 每调用一次该方法就是投票一次,并将投票的次数记录到服务器(用voteCountServer)     */    public void vote(String voteUser, String voteOption) {        // 将投票的次数记录到服务器并获取状态对象        VoteResultState voteResultState = getVoteResultState(voteUser);        if (voteResultState != null) {            // 调用状态对象的voteDetailBehavior()具体行为方法            voteResultState.voteDetailBehavior(voteUser, voteOption, this);        }    }    /**     * 根据投票用户去获取投票次数(状态),在根据投票次数获取投票状态对象     */    private VoteResultState getVoteResultState(String voteUser) {        // 先获取投票人的投票次数        Integer voteCount = voteCountServer.get(voteUser);        if (voteCount == null) {// 第一次投票是以前没有记录            voteCount = 0;        }        voteCount += 1;// 将投票次数添加本次投票        voteCountServer.put(voteUser, voteCount);// 将投票次数添加进服务器        // 再来根据投票次数来选择不同的状态对象        if (voteCount == 1) {// 投了一票            return new NormalVoteState();        } else if (voteCount > 1 && voteCount < 5) {// 重复投票            return new RepetitionVoteState();        } else if (voteCount >= 5 && voteCount < 8) {// 恶意投票            return new SpiteVoteState();        } else if (voteCount >= 8) {// 黑名单            return new BlackListVoteState();        } else {            return null;        }    }}----------------------------------------------------------------------------------------/** * Android Studio java代码的测试类 */public class ExampleUnitTest {    @Test    public void addition_isCorrect() throws Exception {        VoteManager voteManager = new VoteManager();        for (int i = 0; i < 9; i++) {// 用户:"用户甲"投票9次            voteManager.vote("用户甲", "投票选项");        }    }}

状态模式与策略模式的区别

两个模式的重点都是在Context类(VoteManager,HomeToFirmTrip)中对算法或者行为进行调用和安排。
其区别在于:对于策略模式而言,各个算法都可以相互替换的。因为它不像状态模式有各种状态进行限制,而状态模式则一个状态就只对应一个行为,不可以替换行为。

策略模式转换为状态模式:
有这么一个需求,我从家里到公司上班的方法有步行,自行车,公交,汽车等。
如果不考虑时间和费用:那各种方法就是算法,可以用策略模式
而如果将时间费用作为状态:用时最少,成本最低两种状态,那么就只能用状态模式了

参考资料:对比Java设计模式编程中的状态模式和策略模式

0 0