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

原文定义:

   状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变其类【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
请不要重复投票,投票内容为:A4
count:5
你有恶意刷屏行为,取消投票资格!-----投票内容为:A5
count:6
你有恶意刷屏行为,取消投票资格!-----投票内容为:A6
count:7
你有恶意刷屏行为,取消投票资格!-----投票内容为:A7
进入黑名单,将禁止登录和使用本系统,投票内容为:A8
进入黑名单,将禁止登录和使用本系统,投票内容为:A9
进入黑名单,将禁止登录和使用本系统,投票内容为:A10
时间: 2024-10-07 17:40:22

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

《大话设计模式》学习笔记系列--1. 简单工厂模式

简单工厂模式实现了一种"工厂"概念的面向对象设计模式,它可以在不指定对象具体类型的情况下创建对象.其实质是定义一个创建对象的接口,但让实现这个接口的类来决定实例化具体类.工厂方法让类的实例化推迟到子类中进行. 以书本上的计算器程序为例,其UML描述如下: 图中,AddOperator, SubtactOpertor继承算式基类Operator,而CreateOperator则是负责创建一个操作类,而不指明具体的子类类型. 下面,我们来看代码: 首先操作积累: /// <summa

大话设计模式C++实现-第15章-抽象工厂模式

一.UML图 二.概念 抽象方法模式(Abstract Factory):提供一个创建一系列相关或互相依赖对象的接口,而无需指定他们详细的类. 三.包括的角色 (1)抽象工厂 (2)详细工厂:包含详细工厂1和详细工厂2.详细工厂1用于生产详细产品A1和详细产品B1,详细工厂2用于生产详细产品A2和详细产品B2: (3)抽象产品:包含抽象产品A和抽象产品B. (4)详细产品:包含抽象产品A所相应的详细产品A1和A2.以及抽象产品B所相应的详细产品B1和B2. 说明:在<大话设计模式>中,上述的1

《大话设计模式》ruby版代码:简单工厂模式

之前有看过<ruby设计模式>,不过渐渐的都忘记了.现在买了一个大话设计模式,看起来不是那么枯燥,顺便将代码用ruby实现了一下. # -*- encoding: utf-8 -*- #运算类 class Operation attr_accessor :number_a,:number_b def initialize(number_a = nil, number_b = nil) @number_a = number_a @number_b = number_b end def resul

JAVA设计模式(10):结构型-组合模式(Composite)

先看看组合模式的定义吧:"将对象组合成树形结构以表示'部分-整体'的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性." /** * 抽象组件 */ public interface Component { void operation(); } /** * 叶子组件 */ interface Leaf extends Component{ } /** * 容器组件 */ interface Composite extends Component{ } public in

《大话设计模式》学习笔记21:中介者模式

同事间接收消息示例: 1.Mediator: public abstract class Mediator { public abstract void Send(string message, Colleague colleague); } 2.Colleague: public abstract class Colleague { protected Mediator mediator; public Colleague(Mediator mediator) { this.mediator

大话设计模式C++实现-第24章-职责链模式

一.UML图 二.概念 职责链模式(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合.将这个对象连成一条链,并沿着这条链传递该请求,知道有一个对象处理它为止. 三.说明  角色: (1)Handler类:定义一个处理请求的接口. (2)ConcreteHandler类:具体的处理请求的接口. 职责链模式的好处: (1)最关键的是,当客户提交一个请求时,请求时沿链传递直至有一个ConcreteHandler对象负责处理它. (2)

《大话设计模式》学习笔记11:抽象工厂模式

切换数据库类型示例: 1.User类: public class User { public int Id { get; set; } public string Name { get; set; } } 2.AbstractProduct(以User为例): public interface IUser { void Insert(User user); User GetUser(int id); } 3.Product(以User.SQL Server为例): public class Sq

《大话设计模式》学习笔记20:职责链模式

申请审批示例: 1.请求类: public class Request { public string RequestType { get; set; } public string RequestContent { get; set; } public int Number { get; set; } } 2.Handler: public abstract class Manager { protected string name; protected Manager superiorMan

《大话设计模式》ruby版代码:工厂方法模式

一,先看看简单工厂模式 简单工厂模式的优点:工厂类中包含了必要的逻辑判断,根据客户端的选择动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖. 简单工厂模式的缺点:增加功能的时候,就需要增加case的条件分支,也就是要修改工厂类,违背了“开放-封闭原则”. 2,工厂方法模式: # -*- encoding: utf-8 -*- #运算类 class Operation attr_accessor :number_a,:number_b def initialize(number_a =