腾讯面试:自动贩卖机/音频播放器使用了什么设计模式?

状态模式是什么?

状态模式,也被称作状态对象模式,是一种行为设计模式。

当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。

它让对象在其内部状态改变时改变自己的行为。外部调用者无需了解对象内部状态的具体实现,仅需通过简单的接口进行交互

状态模式适用于哪些场景?

当你的对象基于其状态有不同的行为,并且其状态可以在运行时动态转换时,你应该考虑使用状态模式。

如何在Java中实现状态模式?------自动贩卖机

让我们以一个简单的售卖饮料的自动贩卖机为例,来展示如何在Java中实现状态模式。我们首先定义一个状态接口:

csharp 复制代码
public interface State {
    void insertCoin();
    void pushButton();
    void dispense();
}

然后,我们为自动贩卖机的每一种状态实现该接口:

typescript 复制代码
public class NoCoinState implements State {
    public void insertCoin() {
        // 接收硬币,并转换状态
    }

    public void pushButton() {
        // 提示用户先投币
    }

    public void dispense() {
        // 无行为
    }
}

public class HasCoinState implements State {
    public void insertCoin() {
        // 提示用户已经投过币了
    }

    public void pushButton() {
        // 检查库存,然后转换状态
    }

    public void dispense() {
        // 无行为
    }
}

public class SoldState implements State {
    public void insertCoin() {
        // 提示用户等待饮料出货
    }

    public void pushButton() {
        // 提示用户等待饮料出货
    }

    public void dispense() {
        // 出货,然后转换状态
    }
}

最后,我们实现自动贩卖机类:

csharp 复制代码
public class VendingMachine {
    private State noCoinState;
    private State hasCoinState;
    private State soldState;
    
    private State state;  // 当前状态

    public VendingMachine() {
        noCoinState = new NoCoinState();
        hasCoinState = new HasCoinState();
        soldState = new SoldState();
        
        state = noCoinState;  // 初始状态
    }

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

    public void pushButton() {
        state.pushButton();
        state.dispense();
    }

    // 其他方法,例如改变状态...
}

这样,我们的自动贩卖机就可以根据自身的状态决定相应的行为,而无需在一个方法中使用大量的条件语句来判断状态。此外,如果未来我们需要添加更多的状态或者行为,我们也可以很容易地进行拓展。

另一个例子------音频播放器

让我们从一个现实生活的例子看一看状态模式如何被运用到音频播放器的开发中。

音频播放器根据用户的操作和播放条件,可能有多种的状态:例如,"播放状态","暂停状态","停止状态"和"缓冲状态"。不同的状态下,音频播放器的响应行为可能会不同。

首先,定义一个状态接口:

csharp 复制代码
public interface State {
    void play();
    void pause();
    void stop();
    void buffer();
}

然后,实现播放器的每一个状态:

typescript 复制代码
public class PlayingState implements State {
    public void play() {
        // 无响应或提示正在播放
    }

    public void pause() {
        // 暂停播放,并转换到暂停状态
    }

    public void stop() {
        // 停止播放,并转换到停止状态
    }
    
    public void buffer() {
        // 无行为或转到缓冲状态
    }
}

// 类似的,我们还可以定义PauseState、StopState和BufferingState类

在定义了各种状态以后,我们就可以在音频播放器类中使用这些状态:

csharp 复制代码
public class AudioPlayer {
    private State playingState;
    private State pauseState;
    private State stopState;
    private State bufferingState;
    
    private State state;  // 当前状态

    public AudioPlayer() {
        playingState = new PlayingState();
        pauseState = new PauseState();
        stopState = new StopState();
        bufferingState = new BufferingState();
        
        state = stopState;  // 初始状态
    }

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

    public void pause() {
        state.pause();
    }
    
    public void stop() {
        state.stop();
    }

    public void buffer() {
        state.buffer();
    }
    
    // 其他方法,例如改变状态...
}

这样,音频播放器就可以根据当前的状态来进行不同的操作,比如在"播放状态"下如果用户按了播放按钮,播放器可以选择无响应或者给出正在播放的提示,而在"暂停状态"下则会恢复播放。这就是状态模式的魅力,使得音频播放器的代码更易于管理和维护。如果我们需要添加新的状态或行为,也可以轻松地进行拓展。希望通过这篇博文,你能对状态模式有更深入的理解和应用。

相关推荐
2401_857439692 小时前
Spring Boot新闻推荐系统:用户体验优化
spring boot·后端·ux
进击的女IT3 小时前
SpringBoot上传图片实现本地存储以及实现直接上传阿里云OSS
java·spring boot·后端
Мартин.3 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
昨天;明天。今天。4 小时前
案例-表白墙简单实现
前端·javascript·css
数云界4 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd4 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常4 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer4 小时前
Vite:为什么选 Vite
前端
小御姐@stella4 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js