下面用状态模式再来实现一个例子, 来自于我项目的一个案例
因为我要做个对讲机页面. 就是你按一下讲话, 然后再按一下结束讲话那种实时对讲应用.
总体需求是这样的, 一个群里, 一个时间点只能有一个人在讲话. 等级高的可以打断等级低的.
具体说来
每个人的页面上有个对讲按钮, 共有两个状态, 没人讲话 (蓝色) 和有人讲话(红色)
如果一开始时, 没人讲话, 任何一个人讲话, 变成正在讲话状态, 其结束讲话时, 变回无人讲话状态.
如果某人 (当前用户或者其他人) 正在讲话, 对方的权限如果比当前讲话者的权限高, 可以打断其讲话, 通知之前讲话者, 你被我打断了.
如果对方的权限没有当前讲话者的权限高, 通知对方, 请等待正在讲话者讲话结束
别人讲话的开始和结束的操作, 有消息推送, 包括相关信息, 比如名字和讲话等级.
自己讲话, 可以点击按钮, 第一次开始, 第二次结束 也可以按快捷键: 空格键.
不知对需求你看明白了没有?
艾玛当时我写的代码真是惨不忍睹啊, 因为开始时, 并没有抢断这一说. 刚开始的 if else 还可以接受, 后来自己都绕蒙了.
学了状态模式后, 稍微用一下, 代码顿时变得清晰了. 当然也还是使用了 3 次 if else, 不过确实清晰多了....
html 代码
- <!doctype html>
- <head>
- <meta http-equiv="content-type" content="text/html;charset=utf-8">
- <style>
- body{font-size:30px;color:red;} input[type=button]{width:200px;border:none;background:blue;margin:50px
- 10px;color:#fff;padding:10px 20px;cursor:pointer} ::selection{color:#FFF;background:#FF6100}
- button{width:120px;margin:10px; height:20px;background:blue;color:white;outerline:none;}
- </style>
- </head>
- <body>
当前用户的对讲操作界面
- <br />
- <input type="button" value="nobody is talking" />
- <hr />
上下 3 组按钮, 来模拟程序中其他人开始和结束讲话消息来源, 以及空格快捷键.
- <br />
- <button id="lowStart">
- low start
- </button>
- <button id="spaceStart">
- me space start
- </button>
- <button id="highStart">
- high start
- </button>
- <br />
- <button id="lowStop">
- low stop
- </button>
- <button id="spaceStop">
- me space stop
- </button>
- <button id="highStop">
- high stop
- </button>
- <script>
- // 当前讲话者信息.
- var currentName;
- var currenlevel;
- // 无人使用状态
- var silentState = {
- startSpeak: function(name, level) {
- // 所有 console 都是模拟提示消息
- console.log(name + 'is talking');
- talkCtl.setStartStyle(name, level);
- talkCtl.setCurrentState(speakingState);
- },
- stopSpeak: function() {
- // do Nothing
- },
- click: function(name, level) {
- this.startSpeak(name, level);
- }
- }
- // 有人讲话状态
- var speakingState = {
- startSpeak: function(name, level) {
- if (level> currenlevel) {
- console.log(name + 'interupt' + currentName) talkCtl.setStartStyle(name, level);
- talkCtl.setCurrentState(speakingState);
- } else {
- console.log('waiting for' + currentName);
- }
- },
- stopSpeak: function(name, level) {
- if (name == currentName) {
- console.log(name + 'stop talking');
- talkCtl.setStopStyle(name, level);
- talkCtl.setCurrentState(silentState);
- } else {
- console.log('waiting for' + currentName);
- }
- },
- click: function(name, level) {
- if (currentName == name) {
- this.stopSpeak(name, level);
- } else {
- this.startSpeak(name, level);
- }
- }
- };
- // 操作按钮封装
- var talkCtl = {
- init: function(render) {
- this.render = render;
- this.currentState = silentState;
- },
- startSpeak: function(name, level) {
- this.currentState.startSpeak(name, level);
- },
- stopSpeak: function(name, level) {
- this.currentState.stopSpeak(name, level);
- },
- setStartStyle: function(name, level) {
- currentName = name;
- currenlevel = level;
- this.render.style.background = 'red';
- this.render.value = name + 'is talking';
- },
- setStopStyle: function(name, level) {
- currentName = '';
- currenlevel = '';
- this.render.style.background = 'blue';
- this.render.value = 'nobody is talking';
- },
- setCurrentState: function(state) {
- this.currentState = state;
- },
- click: function(name, level) {
- this.currentState.click(name, level);
- },
- }
- // 客户端使用模拟
- var speakBtn = document.querySelector('[type=button]') var spacekeyStart = document.querySelector('#spaceStart');
- var spacekeyStop = document.querySelector('#spaceStop');
- var highStart = document.querySelector('#highStart');
- var highStop = document.querySelector('#highStop');
- var lowStart = document.querySelector('#lowStart');
- var lowStop = document.querySelector('#lowStop');
- talkCtl.init(speakBtn);
- speakBtn.onclick = function() {
- talkCtl.click('me', 2);
- };
- spacekeyStart.onclick = function() {
- talkCtl.startSpeak('me', 2);
- };
- spacekeyStop.onclick = function() {
- talkCtl.stopSpeak('me', 2);
- };
- // 模拟推送来的消息
- highStart.onclick = function() {
- talkCtl.startSpeak('high', 3);
- };
- highStop.onclick = function() {
- talkCtl.stopSpeak('high', 3);
- };
- lowStart.onclick = function() {
- talkCtl.startSpeak('low', 1);
- }
- lowStop.onclick = function() {
- talkCtl.stopSpeak('low', 1);
- }
- </script>
- </body>
来源: http://www.qdfuns.com/article/17398/38b32d1b8d38b95282625b6e0196c020.html