zoukankan      html  css  js  c++  java
  • 设计模式之状态模式(二)

    在上一次的文章里,我们看到,需求的变更,迫使我们需要重新改造现有的糖果机代码来符合这个新提的需求。但是,也并没有难倒我们,至少我们在文末给出了思路和类图,不知道你想的怎么样了呢。

    我们不来虚的,直接进入正题,开启我们的学习之旅。

    实现我们的状态类

    现在是实现一个状态的时候了:我们知道我们要的行为是什么,我们只需要把它变成代码。我们打算完全遵守所写下的状态机代码,但是这一次是分散在不同的类中。比如我们以NoQuarterState类为例。

    public class NoQuarterState implements State {
        GumballMachine gumballMachine;
     
        public NoQuarterState(GumballMachine gumballMachine) {
            this.gumballMachine = gumballMachine;
        }
     
    	public void insertQuarter() {
    		System.out.println("You inserted a quarter");
    		gumballMachine.setState(gumballMachine.getHasQuarterState());
    	}
     
    	public void ejectQuarter() {
    		System.out.println("You haven't inserted a quarter");
    	}
     
    	public void turnCrank() {
    		System.out.println("You turned, but there's no quarter");
    	 }
     
    	public void dispense() {
    		System.out.println("You need to pay first");
    	} 
    	
    }
    

    在完成这些状态类之前,我们需要重新改造糖果机,好让你了解这一切的原理。我们把原来使用整数代表的状态改为状态对象:

        State soldOutState;
    	State noQuarterState;
    	State hasQuarterState;
    	State soldState;
     
    	State state;
    	int count = 0;
    

    这样,我们就有了一个完整的糖果机类

    public class GumballMachine {
     
    	State soldOutState;
    	State noQuarterState;
    	State hasQuarterState;
    	State soldState;
     
    	State state;
    	int count = 0;
     
    	public GumballMachine(int numberGumballs) {
    		soldOutState = new SoldOutState(this);
    		noQuarterState = new NoQuarterState(this);
    		hasQuarterState = new HasQuarterState(this);
    		soldState = new SoldState(this);
    
    		this.count = numberGumballs;
     		if (numberGumballs > 0) {
    			state = noQuarterState;
    		} else {
    			state = soldOutState;
    		}
    	}
     
    	public void insertQuarter() {
    		state.insertQuarter();
    	}
     
    	public void ejectQuarter() {
    		state.ejectQuarter();
    	}
     
    	public void turnCrank() {
    		state.turnCrank();
    		state.dispense();
    	}
     
    	void releaseBall() {
    		System.out.println("A gumball comes rolling out the slot...");
    		if (count != 0) {
    			count = count - 1;
    		}
    	}
     
    	// 后面部分省略
    }
    

    好了,这样子,我们就能继续实现更多的状态类了。比如我们能实现HasQuarterState和SoldState类

    public class HasQuarterState implements State {
    	GumballMachine gumballMachine;
     
    	public HasQuarterState(GumballMachine gumballMachine) {
    		this.gumballMachine = gumballMachine;
    	}
      
    	public void insertQuarter() {
    		System.out.println("You can't insert another quarter");
    	}
     
    	public void ejectQuarter() {
    		System.out.println("Quarter returned");
    		gumballMachine.setState(gumballMachine.getNoQuarterState());
    	}
     
    	public void turnCrank() {
    		System.out.println("You turned...");
    		gumballMachine.setState(gumballMachine.getSoldState());
    	}
    
        public void dispense() {
            System.out.println("No gumball dispensed");
        }
        
    }
    
    public class SoldState implements State {
     
        GumballMachine gumballMachine;
     
        public SoldState(GumballMachine 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("Sorry, you already turned the crank");
    	}
     
    	public void turnCrank() {
    		System.out.println("Turning twice doesn't get you another gumball!");
    	}
     
    	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());
    		}
    	}
    	
    }
    

    检查一下,到目前为止我们做了啥

    你现在有了一个糖果机的实现,他在结构上和前一个版本差异很大,但是功能上却是一样的。我们发现,你已经实现了以下几点:

    • 将每个状态的行为局部化到它自己的类中

    • 将容易产生问题的if语句删除,以方便日后的维护

    • 让每个状态“对修改关闭”,让糖果机“对扩展开放”,因为可以加入新的状态类

    • 创建一个新的代码基和类结构,这更能映射万能糖果公司的图,而且更容易阅读和理解

    定义状态模式

    是的,就在刚才,我们已经实现了状态模式。现在让我们来看看什么是状态模式。

    状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

    让我们好好看下状态模式的类图:

    这个类图和策略模式的类图是一样的。但是虽然类图是一样的,但是两个模式的差别在于它们的“意图”不同。状态模式将一群行为封装在状态对象中,context行为随时可委托到那些状态对象中的一个。对于策略模式而言,客户通常主动指定context所要组合的策略对象是哪一个。

    等等等等,之前不是说有十次抽中一次的游戏吗?怎么还没写出来呢?哈哈哈哈,不急不急,以上内容你都消化了吗?如果你消化的话,请你耐心等待,倘若没有,那请你先好好学习这些吧。我将在下次把抽奖这个搞定。

    拜拜!

    「奔跑吧攻城狮」感谢大家的关注,现在后台回复「设计模式」赠你小编精心挑选设计模式书籍。小编最近开窍,组建了一个技术交流群,回复「加群」即可解锁。

  • 相关阅读:
    16个激发你创新灵感的网站设计资源
    时髦而精巧的Iphone墙纸收集
    分享一个比lightbox配置更方便的jQuery web2.0图片显示插件:Topup
    使用HTML5,CSS3和jQuery来增强网站的用户体验和使用乐趣5
    使用Beautify.js来美化你的jQuery代码
    分享10个jQuery的全景图片展示插件
    使用sublime text 2开发Javacript和jQuery
    分享10个便利的HTML5/CSS3框架
    分享5个javascript的数字格式化函数
    分享10个必备的简化Web设计的HTML5工具
  • 原文地址:https://www.cnblogs.com/dimple91/p/11423339.html
Copyright © 2011-2022 走看看