`
cljspn
  • 浏览: 46943 次
  • 性别: 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)、状态模式...

    C语言设计模式 PDF《C Design Pattern》

    ### C语言设计模式知识点概述 #### 一、C语言与设计模式 在计算机科学领域,设计模式是指在软件设计过程中解决常见问题的一套被广泛接受的解决方案。虽然设计模式最初是在面向对象编程语言中被广泛应用的,但也...

    设计模式23种类图

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

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

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

    《设计模式》中文版

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

    23种java设计模式.pdf

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

    设计模式之禅第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种主要的设计模式进行了详尽的阐述。 首先,我们要理解设计模式的基本概念。设计模式不是代码,而是一种...

Global site tag (gtag.js) - Google Analytics