`
cljspn
  • 浏览: 47564 次
  • 性别: Icon_minigender_1
  • 来自: 长春
最近访客 更多访客>>
社区版块
存档分类
最新评论

设计模式之命令(State)模式

阅读更多

     状态模式是在程序开发时,经常用到的模式。如果没有应用过,而实现业务功能。那你也一定是按照状态模式的路子走的,只不过你没有感觉到而已。它的实现,是要根据对象的内部状态变化,而自动执行相应的功能。
费话就不说了,请看一下源代码,这也是我研究设计模式时看到的一个例子,把其翻译成中文,使个位网友能够看懂些,由于水平有限,只能达到这样,还希望网友多指证,也算是抄来的哈哈,谢谢啊。

public class GumballMachine {
	//这就是那4个状态,每个状态都用一个不同的整数代表,他们符合状态图   
    final static int SOLD_OUT = 0;      //糖果售完状态   
    final static int NO_QUARTER = 1;    //没有钱状态   
    final static int HAS_QUARTER = 2;   //有钱状态   
    final static int SOLD = 3;      //售出糖果   
    //这个实例变量跟踪当前状态,一开始被设为"糖果售完",因为糖果机安装时是没有装糖果的   
    int state = SOLD_OUT;   
    int count = 0;  //这个变量用来追踪机器内的糖果数目   
    //构造器初始糖果库存量当做参数,如果库存不为0的话,机器就进入"没有钱"的状态,等着你向里投钱
    public GumballMachine(int count) {   
        this.count = count;   
        if (count > 0) {   
            state = NO_QUARTER;   
        }   
    }   
    
  //当把钱投入进来,就会执行这里   
    public void insertQuarter() {   
        if (state == HAS_QUARTER) {   
            //如果此时的状态为有钱状态,则通知顾客   
            System.out.println("你不能再向糖果机里投钱了");   
        } else if (state == NO_QUARTER) {   
            //如果是在"没有25分钱"的状态下,我们就接受25分钱,并将状态转换到"有25分钱"   
            state = HAS_QUARTER;   
            System.out.println("你可以向糖果机里投钱");   
        } else if (state == SOLD_OUT) {   
            //如果糖果售完,就拒绝收钱   
            System.out.println("糖果已经卖完,不能再向里投钱了");   
        } else if (state == SOLD) {   
            //如果顾客买到糖果,就需要稍等下,好让状态转换完毕,恢复到"没有25分钱"的状态
            System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");   
        }   
    }   
    //现在,如果顾客试着退回25分钱...   
    public void ejectQuarter() {   
        if (state == HAS_QUARTER) {   
            //如果有25分钱,就退钱,回到"没有25分钱"的状态   
            System.out.println("退钱成功");   
            state = NO_QUARTER;   
        } else if (state == NO_QUARTER) {   
            //如果没有25分钱,当然不能退回   
            System.out.println("没有钱,你不能退钱");   
        } else if (state == SOLD) {   
            //如果顾客已经转动手柄,就不能退钱了,他已经拿到糖果了
        	state = NO_QUARTER;
            System.out.println("对不起,糖果已经卖出不能退钱。");   
        } else if (state == SOLD_OUT) {   
            //如果糖果售完,就不可能接受25分钱,当然也不可能退钱   
            System.out.println("对不起,糖果已经卖完不能退钱");   
        }   
    }   
  //顾客试着转动手柄...   
    public void turnCrank() {   
        if (state == SOLD) {   
            //别想骗过机器拿2次糖果   
            System.out.println("不能再给你了");   
        } else if (state == NO_QUARTER) {   
            //我们需要先投入25分钱   
            System.out.println("你没有投钱糖果不能卖给你");   
        } else if (state == SOLD_OUT) {   
            //没有糖果了   
            System.out.println("糖果机中没有糖果了,你不能进行交易。");   
        } else if (state == HAS_QUARTER) {   
            //成功!他拿到糖果了.改变状态到"售出糖果",然后调用机器的dispense()方法   
            System.out.println("请稍等,一会糖果你就可以拿到了...");   
            state = SOLD;   
            dispense();   
        }   
    }   
    //发放糖果   
    public void dispense() {   
        if (state == SOLD) {   
            //我们正在"售出糖果"状态   
            System.out.println("一个糖果将从这里出来....");   
            count = count - 1;   
            //我们在这里处理"糖果售完"的情况   
            if (count == 0) {//最后一颗,将机器设置到"糖果售完"状态   
                System.out.println("库存为零!");   
                state = SOLD_OUT;   
            } else {    //否则回到"没有25分钱"的状态   
                state = NO_QUARTER;   
            }   
        } else if (state == NO_QUARTER) {   //以下都不应该发生,但如果顾客这么做了,得到的应该是错误消息而不是糖果   
            System.out.println("你需要向糖果机里投钱。。");   
        } else if (state == SOLD_OUT) {   
            System.out.println("糖果已经卖没了");   
        } else if (state == HAS_QUARTER) {   
            System.out.println("请您稍等交易还没有结束。");   
        }   
    }   

}

 

测试就来自已写吧,我提供个思路,就是页面提供几个开关,即按纽、checkbox等在它们的单击事件上GumballMachine实例的内部状态改变。然后看其变化,就可以了。

大家看没看出来,这段代码还有一些“怪的味道”呀,这时如果业务变化了,如果客户是一个中奖的用户,需要糖果机吐出两块糖果,怎么办?,是不是还得在各个方法中把这个状态给加上呀,又得加一个if语句呢,这是一个业务发生了变化,如果业务要无限的变化下去,程序员是不是都要疯了,哈哈。所以要对其进行重构了。

要把这几个状态抽象出来。想到这里看一下代码就明白了。

public interface State {
	//投钱的状态
	public void insertQuarter();
	//退钱的状态
	public void ejectQuarter();
    //按下按纽状态
	public void turnCrank();
    //发放物品状态
	public void dispense();

}

下面是几个实现这个状态接口的实现类。

 

public class HasQuarterState implements State{
	GumballMachineTwo gumballMachine;   
    //增加一个随机数产生器,产生10%的机会   
    Random randomWinner = new Random(System.currentTimeMillis());   
    public HasQuarterState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }   
    public void insertQuarter() {   //这是一个对当前状态不恰当的动作   
        System.out.println("不能再投钱了,已经有钱了。");   
    }   
    
    public void ejectQuarter() {    //退钱并转换状态到NoQuarterState   
        System.out.println("退钱返回");
        //把糖果机从有钱状态改成没钱状态
        gumballMachine.setState(gumballMachine.getNoQuarterState());   
    }   
    
    public void turnCrank() {   
        System.out.println("请稍等,一会糖果你就可以拿到了...");   
        int winner = randomWinner.nextInt(10);   
        //决定这个顾客是否赢了   
        if ((winner == 0) && (gumballMachine.getCount() > 1)) {   
            gumballMachine.setState(gumballMachine.getWinnerState());   
        } else {   
            gumballMachine.setState(gumballMachine.getSoldState());   
        }   
    }   
    public void dispense() {    //这是一个对当前状态不恰当的动作   
        System.out.println("请您稍等交易还没有结束。");   
    }   

}

public class NoQuarterState implements State {
	GumballMachineTwo gumballMachine;

	// 通过构造器得到糖果机的引用
	public NoQuarterState(GumballMachineTwo gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	// 分发物品
	public void dispense() {
		System.out.println("没有钱,不能分发糖果");   
	}

	// 退钱
	public void ejectQuarter() {
		System.out.println("没有钱,不能退钱");

	}

	// 投钱
	public void insertQuarter() {
		// TODO Auto-generated method stub

	}

	// 按纽操作
	public void turnCrank() {
		// TODO Auto-generated method stub

	}

}

public class SoldOutState implements State {
	GumballMachineTwo gumballMachine;

	public SoldOutState(GumballMachineTwo gumballMachine) {
		this.gumballMachine = gumballMachine;
	}

	public void dispense() {
		System.out.println("糖果已经卖没了"); 

	}

	public void ejectQuarter() {
		System.out.println("对不起,糖果已经卖完不能退钱"); 

	}

	public void insertQuarter() {
		System.out.println("糖果已经卖完,不能再向里投钱了");

	}

	public void turnCrank() {
		// TODO Auto-generated method stub

	}

}

public class SoldState implements State{
	GumballMachineTwo gumballMachine;   
    public SoldState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }       
    //以下3个方法对此状态来说都是不恰当的   
    public void insertQuarter() {   
        System.out.println("已向你卖出一个糖果,请稍等,再向里投钱。");   
    }   
    public void ejectQuarter() {   
        System.out.println("对不起,糖果已经卖出不能退钱");   
    }   
    public void turnCrank() {   
        System.out.println("糖果已经卖出,不能再给你了");   
    }   
    //首先让机器发放糖果   
    public void dispense() {   
        gumballMachine.releaseBall();   
        if (gumballMachine.getCount() > 0) {   
            gumballMachine.setState(gumballMachine.getNoQuarterState());   
        } else {   
            System.out.println("Oops, out of gumballs!");   
            gumballMachine.setState(gumballMachine.getSoldOutState());   
        }   
    }   

}

public class WinnerState implements State{
	GumballMachineTwo gumballMachine;   
    //下面都跟SoldState方法一样   
    public WinnerState(GumballMachineTwo gumballMachine) {   
        this.gumballMachine = gumballMachine;   
    }   
    public void insertQuarter() {   
        System.out.println("Please wait, we're already giving you a Gumball");   
    }   
    public void ejectQuarter() {   
        System.out.println("Please wait, we're already giving you a Gumball");   
    }   
    public void turnCrank() {   
        System.out.println("Turning again doesn't get you another gumball!");   
    }   
    //我们在这里发放出2颗糖果,然后进入NoQuarterState或SoldState   
    public void dispense() {   
        System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter");   
        gumballMachine.releaseBall();   
        if (gumballMachine.getCount() == 0) {   
            gumballMachine.setState(gumballMachine.getSoldOutState());   
        } else {   
            gumballMachine.releaseBall();   
            if (gumballMachine.getCount() > 0) {   
                gumballMachine.setState(gumballMachine.getNoQuarterState());   
            } else {   
                System.out.println("Oops, out of gumballs!");   
                gumballMachine.setState(gumballMachine.getSoldOutState());   
            }   
        }   
    }   

}

 

下面是新的糖果类:

public class GumballMachineTwo {
	 //所有的状态都在这里   
    State soldOutState;   
    State noQuarterState;   
    State hasQuarterState;   
    State soldState;   
    
    State winnerState;//十次抽中一次的游戏,新的状态   
    //以及实例变量state   
    State state = soldOutState;   
    int count = 0;//记录糖果数量   
    public GumballMachineTwo(int numberGumballs) {        
        soldOutState = new SoldOutState(this);  //每一种状态也都创建一个状态实例   
        noQuarterState = new NoQuarterState(this);   
        hasQuarterState = new HasQuarterState(this);   
        soldState = new SoldState(this);   
        this.count = numberGumballs;   
        if (numberGumballs > 0) {    //如果超过0颗糖果,状态设为noQuarterState   
            state = noQuarterState;   
        }    
    }   
    //委托给当前状态   
    public void insertQuarter() {   
        state.insertQuarter();   
    }   
    public void ejectQuarter() {   
        state.ejectQuarter();   
    }   
    //dispense()是一个内部动作方法,用户不可以直接要求机器发放糖果   
    public void turnCrank() {   
        state.turnCrank();   
        state.dispense();   
    }   
    //允许其他的对象将机器状态转换到不同的状态   
    void setState(State state) {   
        this.state = state;   
    }   
    //辅助方法释放出糖果,并将count实例变量值减1   
    void releaseBall() {   
        System.out.println("A gumball comes rolling out the slot...");   
        if (count != 0) {   
            count = count - 1;   
        }   
    }   
    int getCount() {   
        return count;   
    }   
    void refill(int count) {   
        this.count = count;   
        state = noQuarterState;   
    }   
    public State getState() {return state;}   
    public State getSoldOutState() {return soldOutState;}   
    public State getNoQuarterState() {return noQuarterState;}   
    public State getHasQuarterState() {return hasQuarterState;}   
    public State getSoldState() {return soldState;}   
    public State getWinnerState() {return winnerState;}   

}

 

11
7
分享到:
评论

相关推荐

    Java设计模式之禅

    《Java设计模式之禅》是一本深入浅出讲解设计模式的书籍,书中不仅包含23种经典设计模式的案例,还详细介绍了设计模式背后的思想和原则,适合初学者以及对设计模式有一定了解的程序员阅读。本书旨在帮助读者理解如何...

    24种设计模式以及混合设计模式

    如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、命令模式(Command)、迭代器模式(Iterator)、访问者模式(Visitor)、备忘录模式(Memento)、状态模式(State)、职责链...

    23种面向对象设计模式

    文档中的“23种设计模式学习笔记.doc”可能包含了对这23种模式的详细解释和实例,而“设计模式之我爱我家.doc”可能从一个更生活化的角度来阐述设计模式的概念。“软件23种设计模式,超级经典的.pdf”可能是对这些...

    设计模式那点事

    包括责任链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式(State)、策略模式(Strategy...

    JAVA设计模式之行为模式

    这是JAVA设计模式中属于行为模式的部分,包括Template(模板模式)、Chain of Responsibility(责任链模式)、Memento(纪念品模式)、Mediator(中介模式)、Strategy(策略模式)、State 、Observer(观察者模式)、Visitor...

    二十三种设计模式【PDF版】

    设计模式之 Command(命令) 什么是将行为封装,Command 是最好的说明. 设计模式之 Observer(观察者) 介绍如何使用 Java API 提供的现成 Observer 设计模式之 Iterator(迭代器) 这个模式已经被整合入Java的...

    《Java设计模式》课后答案-刘伟.rar

    行为型设计模式如策略(Strategy)、模板方法(Template Method)、观察者(Observer)、命令(Command)、迭代器(Iterator)、访问者(Visitor)、状态(State)、职责链(Chain of Responsibility)、解释器...

    《java设计模式》课后习题模拟试题解答——刘伟.zip

    包括策略(Strategy)、模板方法(Template Method)、观察者(Observer)、迭代器(Iterator)、访问者(Visitor)、责任链(Chain of Responsibility)、命令(Command)、备忘录(Memento)、状态(State)、解释...

    c#设计模式

    包括责任链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式...

    设计模式23种类图

    设计模式是软件工程中的一种最佳实践,用于解决在软件开发过程中常见的问题。这些模式是经验丰富的开发者们在解决相似问题时积累的智慧结晶,通过标准化的解决方案,它们可以帮助我们写出更可维护、可扩展和可复用的...

    23种java设计模式.pdf

    " JAVA 设计模式概述" JAVA 设计模式是指在软件设计过程中,为了提高代码的可维护性、灵活性和可扩展性所使用的一些惯用解决方案。JAVA 设计模式可以分为三种:创建模式、结构模式和行为模式。 1. 创建模式 创建...

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

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

    《设计模式》中文版

    设计模式是软件工程中的一种重要概念,它代表了在特定情境下解决常见问题的最佳实践。设计模式并非具体的代码或库,而是一种通用解决方案的描述,可以在多种编程语言中复用。《设计模式》中文版是一本针对Java程序员...

    设计模式之禅第2版超清

    总之,《设计模式之禅》第二版可能会深入剖析Java开发中的设计模式,帮助读者掌握这些模式的精髓,提升软件设计能力。通过阅读书中提供的实例和讲解,开发者能够更好地应对各种复杂的设计挑战,编写出更加优雅、高效...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    设计模式是软件工程中的一种最佳实践,用于解决在软件开发过程中常见的问题。这些模式是由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位大师,通常被称为GoF(Gang of Four),在他们的经典著作...

    C#面向对象设计模式纵横谈(视频与源码)

    C#面向对象设计模式纵横谈(15):(行为型模式) Command 命令模式 C#面向对象设计模式纵横谈(16):(行为型模式) Interpreter 解释器模式 C#面向对象设计模式纵横谈(17):(行为型模式) Mediator 中介者模式 C#...

    JAVA设计模式-chm版

    包括责任链模式(Chain of Responsibility)、命令模式(Command)、解释器模式(Interpreter)、迭代器模式(Iterator)、中介者模式(Mediator)、备忘录模式(Memento)、观察者模式(Observer)、状态模式...

    设计模式PPT---25种设计模式详解

    这份名为“设计模式PPT——25种设计模式详解”的资料,显然是一个深入探讨设计模式的教程,它通过PDF格式对25种主要的设计模式进行了详尽的阐述。 首先,我们要理解设计模式的基本概念。设计模式不是代码,而是一种...

    Headfirst设计模式中文高清PDF+附书源码

    《Headfirst设计模式》是一本深受开发者欢迎的设计模式学习书籍,尤其对于初学者而言,其独特的教学方式使得复杂的概念变得易于理解。这本书以其高清的中文版PDF格式提供,结合书中源码,为读者提供了深入实践的可能...

Global site tag (gtag.js) - Google Analytics