资讯专栏INFORMATION COLUMN

设计模式(10)状态模式(讲解+应用)

lakeside / 2827人阅读

摘要:状态模式对于对象内部的状态,允许其在不同的状态下,拥有不同的行为,对状态多带带封装成类。通过什么来举例子呢设计到多状态,不同状态下各自具有不同行为的东西,而且理解起来相对容易的。下篇更新适配器模式

目录

状态模式

为什么使用状态模式?

应用实例

状态模式

状态模式,顾名思义,肯定是和状态有关,进一步思考,我们在讨论的是设计模式,设计模式中的重要原则对变化的进行封装,顺着这个思路去想,那么是有很多的变化的状态,然后通过状态设计模式,来对这些变化的状态进行封装,故状态设计模式。

状态模式:对于对象内部的状态,允许其在不同的状态下,拥有不同的行为,对状态多带带封装成类。

和策略模式类似,这里是将每一个状态多带带封装成类,每个状态下拥有不同行为。

为什么使用状态模式?

为什么要使用状态模式?通过一个例子来看,对于一些问题,当我们通过一个例子将其具体化之后,我们会发现问题处理起来变得简单,同时理解起来也不会和之前那样晦涩难懂。通过什么来举例子呢?设计到多状态,不同状态下各自具有不同行为的东西,而且理解起来相对容易的。最近在地铁站发现了有个叫5个橙子的投币榨汁机,我们投币10元前,我们就可以获得一杯用5个橙子榨出来的橙汁一杯,如果让我们设计这套系统,要怎么设计呢?首先要有的feature,投币,退币,出橙子,然后其要有的state有没有钱币,10元钱币,大于10元的钱币,小于10元的钱币,橙子售空,还有橙子。动手来写。

//榨汁机
public class MillMachine{
//各种状态
    final static int SOLD_OUT = 0;
    final static int SOLD = 1;
    final static int NO_MONEY = 3;
    final static int HAS_MONEY = 4;
    int state; 
    int count;

    public MillMachine(int count){
        this.count = count;
        if(count>0)
            state = NO_MONEY;
    } 
//插入钱币
    public void insertMoney(){
        if(state == HAS_MONEY)
            System.out.println("You can"t insert Money");
        else if(state == NO_MONEY){
            System.out.println("You insert 10");
            state = HAS_MONEY;
        }
        else if(state == SOLD_OUT)
            System.out.println("Nothing can be bought");
        else if(state == SOLD)
            System.out.prinltn("You will get a cup of juice");
    }
//取出钱币
    public void withdrawMoney(){
        if(state == HAS_MONEY){
            System.out.println("You will get Money");
            state = NO_MONEY;
        }else if(state == NO_MONEY){
            System.out.println("You haven"t insert money");
        }else if(state == SOLD){
            System.out.println("You can"t get back the money");
        }else if(state == SOLD_OUT){
            System.out.println("You haven"t insert money");
        }
    }
//按下榨汁按钮
    public void pressKnob(){
        if(state == SOLD){
            System.out.println("Please wait a minute,you will get a cup of juice");
        }else if(state == SOLD_OUT){
            System.out.prinltn("Sorry,three are"t juice for you");
        }else if(state == NO_MONEY){
            System.out.println("Please insert Money");
        }else if(state == HAS_MONEY){
            System.out.pritln("You will get a cup of juice")
            state = SOLD;
            produce();
        }
    }
//产生果汁
    public void produce(){
        if(state == SOLD){
            System.out.println("You get a cup of juice");
            count--;
            if(count<0)
                state=SOLD_OUT;
            else state=NO_MONEY;
        }else if(state==SOLD_OUT){
            System.out.println("Nothing");
        }else if(state==NO_MONEY){
            System.out.println("Nothing");
        }
        else if(state==HAS_MONEY){
            System.out.println("Nothing");
        }
    }
}

根据代码,我们可以看出,我们一共拥有四种状态,分别为有钱,没钱,售空,未售空。操作有按下榨汁按钮,插入钱币,取出钱币,榨汁,当然榨汁操作并不是我们手动可以触发的。对于其中相应的方法写的也比较详细,各个操作下状态的转换,根据上面的代码,我们可以看出是很繁琐的,而且一旦增加状态,或者是操作,需要我们修改很多的代码,灵活性和可扩展性很差,现在就到了我们的状态设计模式大显身手的时候了。既然是有很多的状态,不同状态下相同的操作行为不同,那么我们就将每一种状态多带带封装成类,然后这些状态分别实现各自不同操作下的行为,这样我们的榨汁机只需要对几个状态对象进行操作就可以了,使得代码变得简洁也方便以后的修改.Show the code

public class MillMachine{
    State noMoneyState;
    State hasMoneyState;
    State soldState;
    State soldOutState;
    State state; 
    int count;

    public MillMachine(int count){
        noMoneyState = new NoMoneyState(this);
        //.....
        this.count = count;
        if(count>0)
            state = NoMoneyState;
    } 

    public void insertMoney(){
        state.insertMoney();
    }

    public void withdrawMoney(){
        state.withdrawMoney();
    }

    public void pressKnob(){
        state.pressKnob();
    }

    public void produce(){
        state.produce();
    }

    public State getNoMoneyState(){
        return this.NoMoneyState;
    }

    public void setState(State state){
        this.state = state;
    }

    
}

public interface State{

    public void insertMoney();

    public void withdrawMoney();

    public void pressKnob();

    public void produce();
}

public class HasMoneyState implements State{

    MillMachine machine;

    public HasMoneyState(MillMachine machine){
        this.machine = machine;
    }

    public void insertMoney(){
        //.......
    }

    public void withdrawMoney(){
        System.out.pritln("you will get your money");
        machine.setState(machine.getNoMoney());
    }

    public void pressKnob(){
        //......
    }

    public void produce(){
        //......
    }

}

通过这种方式来写,让我们的榨汁机类内部的代码量变得更加简洁,针对接口进行编程,同时带来一个弊端就是使得我们的额外的增加了许多的状态类,使得我们的代码量增加了很多。

应用实例

Android中的一个应用实例即使context和state之间,有兴趣的可以针对源码仔细了解,这里先贴出来。

用番茄钟计时来写这篇博客,用掉4个番茄。第五个也已经完成了一半,国庆之后,能有这么充足的时间再来写真的不容易了。

下篇更新适配器模式

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64645.html

相关文章

  • 设计模式(5)装饰器模式讲解+应用

    摘要:装饰器模式在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。通过使用装饰器模式,我们可以实现关闭原有代码,开放现有代码的方式来实现更多的功能。 目录 装饰器模式 为什么使用装饰器模式 应用实例 装饰器模式 看到装饰器是在看《Thinking in Java》一书的时候,看到文件读写那边的时候,有提到装饰器模式,同时在文件读写的那一部分,对于各种读入,写出的方式,代码组...

    RebeccaZhong 评论0 收藏0
  • 深入理解JavaScript

    摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...

    myeveryheart 评论0 收藏0
  • 手挽手带你学VUE:四档 Vue-cli3 Vuex Vue-router

    摘要:安装过后到命令行执行检查版本,如果弹出版本的话恭喜你安装成功,我们开始进行下面的步骤了。全局安装的包名称由改成了。如果你已经全局安装了旧版本的或,你需要先通过卸载它。中的非常类似于事件每个都有一个字符串的事件类型和一个回调函数。 视频教程 由于思否不支持视频外链,视频请移步http://www.henrongyi.top 你能学到什么 在这一期的学习进度中,我们会开始学习在我们工作开...

    Sourcelink 评论0 收藏0
  • 手挽手带你学VUE:四档 Vue-cli3 Vuex Vue-router

    摘要:安装过后到命令行执行检查版本,如果弹出版本的话恭喜你安装成功,我们开始进行下面的步骤了。全局安装的包名称由改成了。如果你已经全局安装了旧版本的或,你需要先通过卸载它。中的非常类似于事件每个都有一个字符串的事件类型和一个回调函数。 视频教程 由于思否不支持视频外链,视频请移步http://www.henrongyi.top 你能学到什么 在这一期的学习进度中,我们会开始学习在我们工作开...

    AlphaWallet 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<