`

读《研磨设计模式》-代码笔记-状态模式-State

阅读更多
声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/





/*

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况
把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化

如果在某段代码中if-else或者switch语句过多,老鸟们常常建议说,可以采用策略模式或者状态模式来重构
在我看来,策略模式仍然需要作if-else的判断,除非需求已明确指出要采用哪个策略
但状态模式似乎更好一些

书上关于用户投票的例子,对我这样的设计模式初学者来说,还是略嫌复杂
网上有一个更简单明了的例子:
http://www.riabook.cn/doc/designpattern/StatePattern.htm

依照上面链接的例子,我写了一个简单示例:


public class StatePatternLjn {

    public static void main(String[] args) {
        SomeObject obj = new SomeObject();
        obj.change();
        obj.change();
        obj.change();
        obj.change();
    }
}

interface State {
    
    void changeState(SomeObject obj);
    
}

class SomeObject {
    
    private State state;

    public SomeObject() {
        state = new Astate();
    }
    
    public void setState(State state) {
        this.state = state;
    }
    
    public void change() {
        this.state.changeState(this);
    }
}

class Astate implements State {

    public void changeState(SomeObject obj) {
        obj.setState(new Bstate());
        System.out.println("a -> b");
    }
}

class Bstate implements State{
    
    public void changeState(SomeObject obj) {
        obj.setState(new Cstate());
        System.out.println("b -> c");
    }
}

class Cstate implements State{
    
    public void changeState(SomeObject obj) {
        obj.setState(new Astate());
        System.out.println("c -> a");
    }
}
 
 和Strategy模式有很多相似的地方,需要说明的是两者的思想都是一致的,只不过封装的东西不同:
 State模式封装的是不同的状态,而Stategy模式封装的是不同的算法
 
 */

import java.util.HashMap;
import java.util.Map;

/*
 * 考虑一个投票的应用:
 * 一个用户只能投一票,若一个用户反复投票,而且投票次数超过5,则认为是恶意刷票,撤消投票记录并取消投票资格
 * 若超过8次,则加入黑名单并禁止再使用系统
 */

interface IVoteState {
    
    /**
     * @param user  投票的用户
     * @param voteItem 投票选项
     * @param context 
     */
    public void vote(String user, String voteItem, VoteContext context);
    
}


//正常投票
class NormalVoteState implements IVoteState {

    public void vote(String user, String voteItem, VoteContext context) {
        context.getMapVoteItem().put(user, voteItem);
        System.out.println("投票成功");
    }
    
}
//重复投票
class RepeatVoteState implements IVoteState {
    
    public void vote(String user, String voteItem, VoteContext context) {
        System.out.println("请不要重复投票");
    }
    
}
//恶意投票
class SpiteVoteState implements IVoteState {
    
    public void vote(String user, String voteItem, VoteContext context) {
        context.getMapVoteItem().remove(user);
        System.out.println("你有恶意刷票行为,取消投票资格!");
    }
    
}
//黑名单
class BlackVoteState implements IVoteState {
    
    public void vote(String user, String voteItem, VoteContext context) {
        System.out.println("进入黑名单");
    }
    
}


class VoteContext {
    
    //通常会维护(持有)一个State对象
    private IVoteState state;
    //Map<用户,投票项>
    private Map<String, String> mapVoteItem = new HashMap<String, String>();
    //Map<用户,投票次数>
    private Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();
    
    //在Context里面进行状态的切换
    public void vote(String user, String voteItem) {
        Integer voteCount = mapVoteCount.get(user);
        if (voteCount == null) {
            voteCount = 0;
        }
        voteCount++;
        mapVoteCount.put(user, voteCount);
        if (voteCount == 1) {
            state = new NormalVoteState();
        } else if (voteCount > 1 && voteCount < 5) {
            state = new RepeatVoteState();
        } else if (voteCount >= 5 && voteCount < 8) {
            state = new SpiteVoteState();
        } else if (voteCount >= 8) {
            state = new BlackVoteState();
        }
        
        state.vote(user, voteItem, this);
        
    }
    
    public Map<String, String> getMapVoteItem() {
        return mapVoteItem;
    }
}


/*
 * 假如我们现在有这样一个需求:投票成功的用户将获得积分奖励,那就势必要更改VoteContext的Vote方法:
   if (voteCount == 1) {
            state = new NormalVoteStateWithPrice();
    }
    ......
 * 这就是书上说的不完美的OCP体验
 */
class NormalVoteStateWithPrice extends NormalVoteState {
    
    public void vote(String user, String voteItem, VoteContext context) {
        super.vote(user, voteItem, context);
        System.out.println("奖励积分:10");
    }
}


/*
 * 上面的示例,是在Context里面进行状态的切换
 * 状态的切换也可以在状态的处理类中实现
 * 这种情况下,若有新的需求(例如新增一种状态),则可增加一个IVoteState而不必修改已有代码
 */
interface IVoteStatee {
    
    public void vote(String user, String voteItem, VoteContextt context);
    
}


//正常投票
class NormalVoteStatee implements IVoteStatee {

    public void vote(String user, String voteItem, VoteContextt context) {
        context.getMapVoteItem().put(user, voteItem);
        System.out.println("投票成功");
        //正常投票完成,维护下一个状态,同一个人再投票就重复了
        context.getMapState().put(user, new RepeatVoteStatee());
        
    }
    
}
//重复投票
class RepeatVoteStatee implements IVoteStatee {
    
    public void vote(String user, String voteItem, VoteContextt context) {
        System.out.println("请不要重复投票");
        if (context.getMapVoteCount().get(user) >= 4) {
            context.getMapState().put(user, new SpiteVoteStatee());
        }
    }
    
}
//恶意投票
class SpiteVoteStatee implements IVoteStatee {
    
    public void vote(String user, String voteItem, VoteContextt context) {
        context.getMapVoteItem().remove(user);
        System.out.println("你有恶意刷票行为,取消投票资格!");
        if (context.getMapVoteCount().get(user) >= 7) {
            context.getMapState().put(user, new BlackVoteStatee());
        }
    }
    
}
//黑名单
class BlackVoteStatee implements IVoteStatee {
    
    public void vote(String user, String voteItem, VoteContextt context) {
        System.out.println("进入黑名单");
    }
    
}


class VoteContextt {
    
    //Map<用户,本用户投票后对应的状态>
    private Map<String, IVoteStatee> mapState = new HashMap<String, IVoteStatee>();
    //Map<用户,投票项>
    private Map<String, String> mapVoteItem = new HashMap<String, String>();
    //Map<用户,投票次数>
    private Map<String, Integer> mapVoteCount = new HashMap<String, Integer>();
    
    public void vote(String user, String voteItem) {
        
        //1.投票数加1
        Integer voteCount = mapVoteCount.get(user);
        if (voteCount == null) {
            voteCount = 0;
        }
        voteCount++;
        mapVoteCount.put(user, voteCount);
        
        //2.维护状态
        IVoteStatee state = mapState.get(user);
        if (state == null) {
            state = new NormalVoteStatee();
        }
        state.vote(user, voteItem, this);
    }

    public Map<String, IVoteStatee> getMapState() {
        return mapState;
    }

    public Map<String, String> getMapVoteItem() {
        return mapVoteItem;
    }

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

//这个类是用来测试的
public class StatePattern {

    public static void main(String[] args) {
        //测试-状态切换在Context里实现
        VoteContext context = new VoteContext();
        for (int i = 0; i < 8; i++) {
            context.vote("Tom", "A");
        }
        
        System.out.println();
        
        //测试-状态切换由状态实现类切换
        VoteContextt contextt = new VoteContextt();
        for (int i = 0; i < 8; i++) {
            contextt.vote("Tom", "A");
        }
    }

}



1
7
分享到:
评论

相关推荐

    研磨设计模式-配套源代码

    "研磨设计模式-配套源代码"很显然是一份与学习和理解设计模式相关的资源,其中包含了实际的编程示例。这份压缩包可能包括了多种常见设计模式的实现,如单例模式、工厂模式、观察者模式、装饰器模式等,通过源代码的...

    研磨设计模式-配套源代码.7z

    《研磨设计模式》是一本深入探讨软件设计模式的书籍,其配套源代码包含了许多经典设计模式的实际应用示例。这些源代码可以帮助读者更直观地理解设计模式的原理和使用方法,进一步提升软件开发能力。 设计模式是软件...

    研磨设计模式-配套源代码.rar

    《研磨设计模式》是一本深入探讨软件设计模式的书籍,配套源代码是作者为了帮助读者更好地理解和应用书中介绍的设计模式而提供的实践示例。设计模式是软件开发中经过实践检验的、解决常见问题的模板,它为软件设计...

    研磨设计模式-配套源代码 UTF-8格式

    《研磨设计模式》是一本深入探讨软件设计原则与实践的经典书籍,其配套源代码提供了丰富的实例,帮助读者更好地理解和应用各种设计模式。这个UTF-8格式的压缩包包含了书中介绍的各种设计模式的实现,是学习和研究...

    研磨设计模式-陈臣.epub

    “1.1 设计模式是什么 1.1.1 什么是模式 从字面上理解,模,就是模型、模板的意思;式,就是方式、方法的意思。综合起来,所谓模式就是:可以作为模型或模板的方式或方法。... “研磨设计模式”。 iBooks.

    研磨设计模式--chjavach的博客文章

    研磨设计模式的过程是持续学习和实践的过程,chjavach的博客文章提供了深入探讨这些模式的宝贵资源,值得我们仔细阅读和学习。通过深入理解和运用这些设计模式,可以提升个人的编程技巧,同时也为团队合作和项目维护...

    研磨设计模式-陈臣.王斌.扫描高清版PDF

    设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。 使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;...

    研磨设计模式-陈臣pdf

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式书-配套源代码(全)

    1:本源代码是《研磨设计模式》一书的配套源代码 2:每个模式的示例源代码放在一个单独的文件夹下,以该模式的英文名称命名 3:每个模式下分成多个example,按照书的示例顺序分别命名为example1、example2.........

    研磨设计模式-陈臣.mobi kindle版

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式源码

    《研磨设计模式源码》是一份非常宝贵的资源,它提供了设计模式的实践代码,帮助开发者深入理解并应用这些模式。设计模式是软件工程中经过长期实践总结出来的一套通用解决方案,它们描述了在特定场景下如何解决常见...

    研磨设计模式 源代码

    《研磨设计模式》是一本深入探讨软件设计模式的经典书籍,源代码包含了书中所讲解的各种设计模式的实际应用示例。设计模式是软件工程中的重要概念,它们是经过反复验证、在特定情境下解决常见问题的有效解决方案。...

    研磨设计模式-part2

    第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24...

    研磨设计模式-part4

    第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24...

    研磨设计模式-part3

    第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24...

    研磨设计模式全部源代码

    这个压缩包“研磨设计模式全部源代码”包含了多种设计模式的实现,这些模式可以帮助开发者写出更可维护、可扩展和可复用的代码。下面将详细讲解其中可能包含的一些重要设计模式及其应用。 1. 工厂模式:这是最简单...

    研磨设计模式带书签完整版228M.7z.001

    《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,...

    研磨设计模式(完整带书签).part2.pdf

    第18章 状态模式(State) 第19章 备忘录模式(Memento) 第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24...

    研磨设计模式PDF

    《研磨设计模式》这本书是陈臣和王斌两位作者合作的成果,专注于讲解软件设计中的模式应用。设计模式是软件工程中的一种最佳实践,它总结了在特定上下文中解决问题的常见方法,使得开发者可以复用这些解决方案,提高...

    研磨设计模式 演示源代码

    "研磨设计模式 演示源代码"这个资源包含了对设计模式的详细解释和实例分析,旨在帮助学习者深入理解和应用这些模式。 1. **单例模式**:确保一个类只有一个实例,并提供一个全局访问点。在资源管理、缓存或者线程池...

Global site tag (gtag.js) - Google Analytics