状态模式

 

1、定义:

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了他的类。

2、代码:

/**
 * 封装一个投票状态的行为
 */
public interface VoteState {

    /**
     * 处理状态对应的行为
     * @param user 投票人
     * @param voteItem 投票项
     * @param voteManager  投票上下文,用来实现状态对应的功能处理的时候,可以回调上下文的数据
     */
    public void vote(String user,String voteItem,VoteManager voteManager);

}


/**
 * 正常投票
 */
public class NormalVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //正常投票
        //记录到投票记录中
        System.out.println("正常投票。");
    }

}


/**
 * 重复投票
 */
public class RepeatVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //重复投票
        //暂不处理
        System.out.println("请不要重复投票!");
    }

}


/**
 * 恶意投票
 */
public class SpiteVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //恶意投票
        //取消用户的投票资格、并取消投票记录
        String s=voteManager.getMapVote().get(user);
        if(s!=null){
            voteManager.getMapVote().remove(user);
        }
        System.out.println("你有恶意刷票行为,取消投票资格");
    }

}



/**
 * 黑名单投票
 */
public class BlackVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {

        //黑名单
        //记入黑名单中,禁止登陆系统了
        System.out.println("记入黑名单中,将禁止登陆和使用本系统");
    }

}

//投票管理类
public class VoteManager {

    /**
     * 持有状态处理对象
     */
    private VoteState state=null;
    /**
     * 记录用户投票的结果,Map<用户名,投票的选项>
     */
    private Map<String,String> mapVote=new HashMap<String, String>();

    /**
     * 记录用户投票次数Map<用户名,投票次数>
     */
    private Map<String,Integer> mapVoteCount=new HashMap<String, Integer>();

    /**
     * 获取记录用户投票结果
     * @return
     */
    public Map<String,String> getMapVote(){
        return mapVote;
    }

    /**
     * 投票
     * @param user
     * @param voteItem
     */
    public void vote(String user,String voteItem){
        //1、先为该用户增加投票的次数
        Integer oldVoteCount=mapVoteCount.get(user);
        if(oldVoteCount==null){
            oldVoteCount=0;
        }
        oldVoteCount++;
        mapVoteCount.put(user,oldVoteCount);

        //2、判断该用户投票的类型,就相当于是判断对应的状态
        if(oldVoteCount==1){//正常投票
            state=new NormalVoteState();
        }else if(oldVoteCount>1 && oldVoteCount<5){//重复刷票
            state=new RepeatVoteState();
        }else if(oldVoteCount>5 && oldVoteCount<8){//恶意刷票
            state=new SpiteVoteState();
        }else{//黑名单投票
            state=new BlackVoteState();
        }
        state.vote(user,voteItem,this);
    }

}

Client类:

public class Client {

    public static void main(String[] args) {
        VoteManager vm=new VoteManager();
        for (int i=0;i<10;i++){
            vm.vote("user1","A");
        }
    }
}

结果输出:

正常投票。
请不要重复投票!
请不要重复投票!
请不要重复投票!
记入黑名单中,将禁止登陆和使用本系统
你有恶意刷票行为,取消投票资格
你有恶意刷票行为,取消投票资格
记入黑名单中,将禁止登陆和使用本系统
记入黑名单中,将禁止登陆和使用本系统
记入黑名单中,将禁止登陆和使用本系统

3、讲解

3.1、状态和行为

状态:指的是对象实例的属性的值

行为:指的就是对象的功能,具体点说,行为大多可以对应到方法上。

状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对象的不同功能。

也就是说,状态和行为是相关联的,他们的关系可以描述为:状态决定行为。

3.2、行为的平行性

平行性指的是各个状态的行为所处的层次是一样的,相互是独立的,没有关联的,是根据不同的状态来决定到底走平行线的哪一条。行为不同,对应的实现也是不同的,相互之间是不可替换的。

平等性 强调的是可替换性,同一行为发生时,可以根据条件挑选任意一个实现来进行处理。

3.3、状态模式和策略模式区别

结构万全相同,但是目的、实现、本质却是完全不一样的。行为也是一个重要的区别,状态模式是平行性的,不可相互替换的。

策略模式的行为是平等性的,是可以相互替换的。

3.4、 状态的维护和转换控制

状态的维护:是指维护状态的数据,给状态设置不同的状态值。

状态的转换:是根据状态的变化来选择不同的状态处理对象。

通常在两个地方可以进行状态的维护和转换控制

  • 在上下文中。状态本身通常被实现为上下文对象的状态,因此可以在上下文中进行状态维护,当然也就可以控制状态的转换了。上面投票实例就是采用这种方式。
  • 在状态的处理类中。当每个状态处理对象处理完自身状态所对应的功能后,可以根据需要指定后继状态,以便让应用能正确处理后续请求。如下实例:
/**
 * 封装一个投票状态的行为
 */
public interface VoteState {

    /**
     * 处理状态对应的行为
     * @param user 投票人
     * @param voteItem 投票项
     * @param voteManager  投票上下文,用来实现状态对应的功能处理的时候,可以回调上下文的数据
     */
    public void vote(String user, String voteItem, VoteManager voteManager);

}

/**
 * 正常投票
 */
public class NormalVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //正常投票
        //记录到投票记录中
        voteManager.getMapVote().put(user,voteItem);
        System.out.println("恭喜您投票成功。");
        //正常投票完成,维护下一个状态,同一个人再投票就重复了。
        voteManager.getMapState().put(user,new RepeatVoteState());
    }
}



/**
 * 重复投票
 */
public class RepeatVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //重复投票
        //暂不处理
        System.out.println("请不要重复投票!");
        //重复投票完成,维护下一个状态,重复投票5次,就算恶意投票了
        if(voteManager.getVoteStateCount().get(user)>=4){
            voteManager.getMapState().put(user,new SpiteVoteState());
        }
    }

}


/**
 * 恶意投票
 */
public class SpiteVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {
        //恶意投票
        //取消用户的投票资格、并取消投票记录
        String s=voteManager.getMapVote().get(user);
        if(s!=null){
            voteManager.getMapVote().remove(user);
        }
        System.out.println("你有恶意刷票行为,取消投票资格");

        //恶意投票完成,投票到8次,就进入黑名单
        if(voteManager.getVoteStateCount().get(user)>=7){
            voteManager.getMapState().put(user,new BlackVoteState());
        }
    }

}


/**
 * 黑名单投票
 */
public class BlackVoteState implements VoteState {

    public void vote(String user, String voteItem, VoteManager voteManager) {

        //黑名单
        //记入黑名单中,禁止登陆系统了
        System.out.println("记入黑名单中,将禁止登陆和使用本系统");
    }

}

public class VoteManager {

    /**
     * 持有状态处理对象
     */
    private VoteState state=null;

    /**
     * 记录当前每个用户对应的状态处理对象,每个用户当前的状态是不同的
     */
    private Map<String,VoteState> mapState=new HashMap<String, VoteState>();

    /**
     * 记录用户投票的结果,Map<用户名,投票的选项>
     */
    private Map<String,String> mapVote=new HashMap<String, String>();

    /**
     * 记录用户投票次数Map<用户名,投票次数>
     */
    private Map<String,Integer> mapVoteCount=new HashMap<String, Integer>();

    /**
     * 获取记录用户投票结果
     * @return
     */
    public Map<String,String> getMapVote(){
        return mapVote;
    }

    //获取记录每个用户对应的状态处理对象状态
    public Map<String,VoteState> getMapState(){
        return mapState;
    }

    public Map<String,Integer> getVoteStateCount(){
        return mapVoteCount;
    }

    /**
     * 投票
     * @param user
     * @param voteItem
     */
    public void vote(String user,String voteItem){
        //1、先为该用户增加投票的次数
        Integer oldVoteCount=mapVoteCount.get(user);
        if(oldVoteCount==null){
            oldVoteCount=0;
        }
        oldVoteCount++;
        mapVoteCount.put(user,oldVoteCount);

        //2、获得该用户的投票状态
        VoteState state=mapState.get(user);
        if(state==null){
            state=new NormalVoteState();
        }
        state.vote(user,voteItem,this);
    }


}
public class Client {

    public static void main(String[] args) {
        VoteManager vm=new VoteManager();
        for (int i=0;i<10;i++){
            vm.vote("user1","A");
        }
    }
}
恭喜您投票成功。
请不要重复投票!
请不要重复投票!
请不要重复投票!
你有恶意刷票行为,取消投票资格
你有恶意刷票行为,取消投票资格
你有恶意刷票行为,取消投票资格
记入黑名单中,将禁止登陆和使用本系统
记入黑名单中,将禁止登陆和使用本系统
记入黑名单中,将禁止登陆和使用本系统

选用何种方式?

  • 如果状态转换的规则是一定的,一般不需要进行什么扩展规则,适合上下中统一进行状态维护。
  • 如果状态的转换取决于前一个状态动态处理的结果,或者依赖于外部数据,为了增强灵活性,这种情况下,在状态处理类中进行状态的维护。

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值