《大话设计模式》——读后感 (10)无尽加班何时休?——状态模式

来源:互联网 发布:广联达计价软件图标 编辑:程序博客网 时间:2024/05/16 12:05

原文定义:

   状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变其类【DP】

 

UML结构图:

  

 

背景:

    看到此模式,酝酿了好久才决定对状态模式进行总结。光看原文定义,实在没有获取到什么有用的价值。

       第一眼看到状态模式,感觉这不就是一个简单工工厂模式吗?但是仔细看看其他人的博客,发现状态模式和简单工厂模式还是有一定的区别的,最明显的是Context类持有了State,这一点和简单工厂区别很大。但是我发现状态模式又和策略模式很像,或者说是太像了。同样有抽象接口,具体实现类,Context上下文类, 以及Context里面也含有一个State抽象,简直一摸一样啊。而且网上其他很多人的博客在解释状态模式的时候,用的分明就是策略模式的例子,真的很无解!

       思量再三,对《大话设计模式》中对状态模式进行反复的研究,并且上网找了很多的微博进行阅读和理解,最终才有一点收获,并且再次进行总结。

 

其实看了很多的微博以后,再次来理解定义的时候,我们还是能获取一点有用的信息的:

  状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变其类【DP】

 

   1、"对象的内在状态":其实这和我们在策略模式中理解的具体策略,在简单工厂中的具体算法是类似的,称呼不同而已。

   2、“当一个对象的内在状态改变时允许改变其行为”: 举例说A对象内部持有的B改变了,此时允许B改变A的具体行为操作,即状态控制行为

   

适用性 

在下面的两种情况下均可使用State模式:

1) • 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2) • 代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

 

 

 

下面分享我在网上找到的一个关于投票的优秀案例,我对其进行改造,看起来更加的符合状态模式定义:

 考虑一个在线投票系统的应用,要实现控制同一个用户只能投一票,如果一个用户反复投票,而且投票次数超过5次,则判定为恶意刷票,要取消该用户投票的资格,当然同时也要取消他所投的票;如果一个用户的投票次数超过8次,将进入黑名单,禁止再登录和使用系统。

  要使用状态模式实现,首先需要把投票过程的各种状态定义出来,根据以上描述大致分为四种状态:正常投票、反复投票、恶意刷票、进入黑名单。然后创建一个投票管理对象(相当于Context)。

 

投票的抽象接口:

package com.sjmx.state;public interface VoteState {    /**     * 处理状态对应的行为     *      * @param user     *            投票人     * @param voteItem     *            投票项     * @param voteManager     *            投票上下文,用来在实现状态对应的功能处理的时候, 可以回调上下文的数据     */    public void vote(String user, String voteItem, VoteManager voteManager,int count);}

 

具体状态类——正常投票:

package com.sjmx.state;/* *  * 具体状态类——正常投票 */public class NormalVoteState implements VoteState {    @Override    public void vote(String user, String voteItem, VoteManager voteManager,int count) {        // 正常投票,记录到投票记录中        if(1 == count){            voteManager.getMapVote().put(user, voteItem);            System.out.println("恭喜投票成功,投票内容为:" + voteItem);                        voteManager.state = new RepeatVoteState();        }     }}

 

具体状态类——重复投票:

package com.sjmx.state;/* *  *  具体状态类——重复投票 */public class RepeatVoteState implements VoteState {    @Override    public void vote(String user, String voteItem, VoteManager voteManager,int count) {                // 重复投票,暂时不做处理        if(count > 1 && count < 5){            System.out.println("请不要重复投票,投票内容为:" + voteItem);        }else{            voteManager.state = new SpiteVoteState();            voteManager.voteByChange(user, voteItem, count);        }    }}

 

恶意投票:

package com.sjmx.state;public class SpiteVoteState implements VoteState {        @Override    public void vote(String user, String voteItem, VoteManager voteManager,int count) {                // 恶意投票,取消用户的投票资格,并取消投票记录        if(count >= 5 && count < 8)        {            System.out.println("count:" + count);            String str = voteManager.getMapVote().get(user);            if (str != null) {                voteManager.getMapVote().remove(user);            }            System.out.println("你有恶意刷屏行为,取消投票资格!-----投票内容为:" + voteItem);        }else{            voteManager.state = new BlackVoteState();            voteManager.voteByChange(user, voteItem, count);        }    }}

 

记录黑名单中,禁止登录系统:

package com.sjmx.state;public class BlackVoteState implements VoteState {    @Override    public void vote(String user, String voteItem, VoteManager voteManager,int count) {                // 记录黑名单中,禁止登录系统        System.out.println("进入黑名单,将禁止登录和使用本系统,投票内容为:" + voteItem);    }}

 

状态管理类:

package com.sjmx.state;import java.util.HashMap;import java.util.Map;public class VoteManager {        // 持有状体处理对象    public VoteState state = null;        // 记录用户投票的结果,Map<String,String>对应Map<用户名称,投票的选项>    public Map<String, String> mapVote = new HashMap<String, String>();        // 记录用户投票次数,Map<String,Integer>对应Map<用户名称,投票的次数>    public Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();        public VoteManager(String user) {        state =  new NormalVoteState();    }        /**     * 获取用户投票结果的Map     */    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 += 1;        mapVoteCount.put(user, oldVoteCount);                this.voteByChange(user, voteItem, oldVoteCount);    }            public void voteByChange(String user, String voteItem, int count){        // 然后转调状态对象来进行相应的操作        state.vote(user, voteItem, this,count);    }                    }

 

客户端:

package com.sjmx.state;public class Client {    public static void main(String[] args) {                VoteManager vm = new VoteManager("jack");        for(int i=1;i<11;i++){            vm.vote("u1","A"+i);        }    }}

 

运行结果:

恭喜投票成功,投票内容为:A1请不要重复投票,投票内容为:A2请不要重复投票,投票内容为:A3请不要重复投票,投票内容为:A4count:5你有恶意刷屏行为,取消投票资格!-----投票内容为:A5count:6你有恶意刷屏行为,取消投票资格!-----投票内容为:A6count:7你有恶意刷屏行为,取消投票资格!-----投票内容为:A7进入黑名单,将禁止登录和使用本系统,投票内容为:A8进入黑名单,将禁止登录和使用本系统,投票内容为:A9进入黑名单,将禁止登录和使用本系统,投票内容为:A10

 

阅读全文
0 0