supce's blog

IFE Task 15


任务目的

  • 练习JavaScript面向对象设计
  • 实践一些基础的设计模式

任务描述

  • 基于上一任务,我们继续改善
  • 第二代宇宙飞船系统进步了很多,但是我们依然无法知道飞船的能源消耗情况,可能有的时候我们发出开始飞行的指令,但飞船早就没有能量了,所以我们再次进行升级,这次我们需要增加一个飞船状态的监视系统
  • 我们为每个飞船增加一个信号发射器,飞船会通过BUS系统定时(比如每秒)广播自己的飞行状态。发送的时候,我们通过已经安装在飞船上的Adapter把状态数据翻译成二进制码形式,把飞船自身标示,飞行状态,能量编码成一个16位的二进制串,前四位用于飞船自身标示,接下来4位表示飞行状态,0010为停止,0001为飞行,1100表示即将销毁,后八位用于记录飞船剩余能源百分比
  • 行星上有一个信号接收器,用于通过BUS系统接受各个飞船发送过来的信号
  • 当信号接收器接收到飞船信号后,会把信息传给数据处理中心(DC),数据处理中心依然是调用Adapter模块,把这些二进制数据转为对象格式存储在DC中
  • 实现一个行星上的监视大屏幕,用来显示所有飞船的飞行状态及能源情况,当数据处理中心飞船数据发生变化时,它会相应在监视器上做出变化

整体思路

由于任务越来越多,这次把类重新聚合一下。

行星到宇宙飞船的信号是通过BUS传输的,利用单例模式实现一个BUS类,BUS类有一个接收信号的方法,该方法带有两个参数,一个参数是传输的信号,另一个表示端口号用于区别信号是从行星发往飞船还是飞船发往行星。

//BUS 单例
function Bus(){
    var instance = this;
    Bus = function(){
        return instance;
    };
}
Bus.prototype = {
    //port为1时表示从行星发往太空,port为2时表示从太空发往行星
    receive : function(order,port){
        if(port == "1"){
            var timer = null;
            timer = setInterval(run,300);
            function run(){
                var num = Math.floor(Math.random()*10+1);
                if(num > 1){
                    for(var i=0;i<crafts.length;i++){
                        // crafts[i].receiveCommond(order);
                        crafts[i].Mediator.receive(order);
                    }
                    clearInterval(timer);
                }else{
                    msgControl("信息传递失败!正在重试,fight だよ!");
                }
            }
        }else if(port == "2"){
            //得到行星上的信号收发器
            var mediator = new Mediator();
            mediator.receive(order);
        }else{
            msgControl("该端口暂时还未开放");
        }
    }
}

在行星上有一个信号收发器,可以向飞船发送信息以及接收从飞船传递来的信息。在信号收发器上有一个信号适配器,用于对信号进行编码和解码,收发器收到信号后会对信号进行解码,然后传递给DC(数据控制中心)。

//行星信号收发器
function Mediator(){
    var instance = this;
    Mediator = function(){
        return instance;
    };
    //收发器上的信号适配器
    this.Adapter = {
        //信号编码器
        encode : function(commond){
            var str = "";
            var id = commond.id;
            var order = commond.commond;
            switch(id){
                case '0':str += "00";break;
                case '1':str += "01";break;
                case '2':str += "10";break;
                case '3':str += "11";break;
            }
            switch(order){
                case 'start':str += "0001";break;
                case 'stop':str += "0010";break;
                case 'destroy':str += "1100";break;
            }
            return str;
        },
        //信号解码器
        decode : function(signal){
            var id,engine,supply,state,power;
            switch(signal.substring(0,3)){
                case '000':id = "1";break;
                case '001':id = "2";break;
                case '010':id = "3";break;
                case '011':id = "4";break;
            }
            switch(signal.substring(3,6)){
                case '000':engine = "用恨飞行";break;
                case '001':engine = "手摇飞行";break;
                case '010':engine = "电能飞行";break;
                case '011':engine = "核能飞行";break;
            }
            switch(signal.substring(6,9)){
                case '000':supply = "用爱充能";break;
                case '001':supply = "手摇充能";break;
                case '010':supply = "燃料充能";break;
                case '011':supply = "核变充能";break;
            }
            switch(signal.substring(9,13)){
                case '0001':state = "飞行";break;
                case '0010':state = "暂停";break;
                case '1100':state = "销毁";break;
                case '1111':state = "充能";break;
            }
            power = parseInt(signal.substring(13));
            return {
                id : id,
                engine : engine,
                supply : supply,
                state : state,
                power : power
            };
        }
    }
}
Mediator.prototype = {
    sendCommond : function(commond){
        var commond = this.Adapter.encode(commond);
        var bus = new Bus();
        bus.receive(commond,1);
    },
    receive : function(signal){
        var signal = this.Adapter.decode(signal);
        // console.log(signal);
        var dc = new DC();
        dc.receive(signal);
    }
}

飞船升级后,在飞船上配备了信号收发器和信号适配器。能够通过BUS接收从行星发射的命令和向行星发送当前飞船的状态。

//飞船类
function Craft(id,engine,supply){
    //飞船id
    this.id = id;
    //飞船引擎控制飞船速度
    this.engine = engine;
    //飞船供能系统控制能量恢复速度
    this.supply = supply;
    //飞船能量
    this.power = 100;
    //飞船是否正在飞行
    this.state = "stop";
    //控制飞船动力系统
    this.timer = null;
    //飞船上的信号收发器
    this.Mediator = {
        //接收从bus传入的信息
        receive : function(commond){
            var commond = this.Adapter.decode(commond);
            if(commond.id == this.id){
                order = commond.commond;
                switch(order){
                    case 'start':
                        msgControl("有嘎达~ 信息传递成功!");
                        this.powerConsume();
                        this.state = "start";
                        this.start();
                        break;
                    case 'stop':
                        msgControl("有嘎达~ 信息传递成功!");
                        this.powerAdd();
                        this.state = "stop";
                        this.stop();
                        break;
                    case 'destroy':
                        msgControl("有嘎达~ 信息传递成功!");
                        this.destroy();
                        break;
                }
            }
        }.bind(this),
        //向bus传送信息
        send : function(){
            var _this = this;
            var msg = {
                id : _this.id,
                engine : _this.engine,
                supply : _this.supply,
                state : _this.state,
                power : _this.power
            }
            var signal = this.Adapter.encode(msg);
            var bus = new Bus();
            //从端口2发往行星
            bus.receive(signal,2);
        }.bind(this)
    };
    //飞船上的信号适配器
    this.Adapter = {
        //对于收到的信息进行解码
        decode : function(commond){
            var str_id = "",str_order = "";
            switch(commond.substring(0,2)){
                case '00':
                    str_id = 0;break;
                case '01':
                    str_id = 1;break;
                case '10':
                    str_id = 2;break;
                case '11':
                    str_id = 3;break;
            }
            switch(commond.substring(2)){
                case '0001':
                    str_order = "start";break;
                case '0010':
                    str_order = "stop";break;
                case '1100':
                    str_order = "destroy";break;
            }
            return {
                id : str_id,
                commond : str_order
            }
        },
        //对于发送的信息进行编码
        encode : function(commond){
            //id engine supply power各占3位,state占4位 共16位
            var str = "";
            var id=commond.id,engine=commond.engine,supply=commond.supply,
                state=commond.state,power=commond.power;
            switch(id){
                case 0:str += "000";break;
                case 1:str += "001";break;
                case 2:str += "010";break;
                case 3:str += "011";break;
            }
            switch(engine){
                case 'speed_one':str += "000";break;
                case 'speed_two':str += "001";break;
                case 'speed_three':str += "010";break;
                case 'speed_four':str += "011";break;
            }
            switch(supply){
                case '900':str += "000";break;
                case '600':str += "001";break;
                case '300':str += "010";break;
                case '100':str += "011";break;
            }
            switch(state){
                case 'start':str += "0001";break;
                case 'stop':str += "0010";break;
                case 'destroy':str += "1100";break;
                //能量用完后暂停飞行开始充能
                case 'charge':str += "1111";break;
            }
            if(0< power <100){
                power = "0" + power;
                str += power;
            }else if(power == 100){
                str += "100";
            }else if(power == 0){
                str += "000";
            }
            return str;
        }
    }
}
Craft.prototype = {
    constructor: Craft,
    start : function(){
        msgControl("Nozomi power注入! 嗨~ 噗咻!" + (this.id+1) + "号飞船已经起飞");
        var craftImg = document.querySelector("." + craftsMap[this.id]);
        craftImg.classList.add("craft_start");
        craftImg.classList.add(this.engine);
        this.Mediator.send();
    },
    stop : function(){
        msgControl("sa si su se so!" + (this.id+1) + "号飞船停止飞行");
        var craftImg = document.querySelector("." + craftsMap[this.id]);
        craftImg.classList.remove("craft_start"); 
        this.Mediator.send();
    },
    destroy : function(){
        msgControl("dame! dame!" + (this.id+1) + "号飞船被销毁了");
        //先停止再销毁
        var id = this.id;
        var craftImg = document.querySelector("." + craftsMap[id]);
        craftImg.classList.remove("craft_start");
        clearInterval(this.timer);
        //销毁飞船
        craftImg.classList.remove(this.engine);
        craftImg.classList.remove("craft_create");
        this.state = "destroy";
        this.power = 0;
        this.Mediator.send();
        //销毁控制板
        document.getElementById(id).classList.add("li_hidden");
        //将飞船从轨道撤下
        for(var i=0,len=crafts.length;i<len;i++){
            if(crafts[i].id == id){
                crafts.splice(i,1);
                break;
            }
        }
    },
    powerConsume : function(){
        var speedMap = {
            speed_one : 900,
            speed_two : 600,
            speed_three : 300,
            speed_four : 100 
        };
        var _this = this;
        if(this.timer){
            clearInterval(this.timer);
        }
        this.timer = setInterval(run,speedMap[this.engine]);
        function run(){
            if(_this.power>0){
                _this.power = _this.power - 1;
                var craftImg = document.querySelector("." + craftsMap[_this.id]);
                craftImg.innerHTML = _this.power + "%";
            }else{
                _this.stop();
                _this.state = "charge";
                clearInterval(_this.timer);
                _this.powerAdd();
            }
            _this.Mediator.send();
        }
    },
    powerAdd : function(){
        var _this = this;
        if(this.timer){
            clearInterval(this.timer);
        }
        this.timer = setInterval(run,parseInt(this.supply));
        function run(){
            if(_this.power<100){
                _this.power = _this.power + 1;
                var craftImg = document.querySelector("." + craftsMap[_this.id]);
                craftImg.innerHTML = _this.power + "%";
            }else{
                if(_this.state == "charge"){
                    _this.start();
                    _this.state = "start";
                    clearInterval(_this.timer);
                    _this.powerConsume();
                }else{
                    clearInterval(_this.timer);
                }
            }
            _this.Mediator.send();
        }
    },
}

最后还需要增加一个DC,将飞船发送过来的信息展现在大屏幕上。

//行星DC
function DC(){
    var instance = this;
    DC = function(){
        return instance;
    };
}
DC.prototype = {
    receive : function(signal){
        //console.log(signal);
        var screen;
        switch(signal.id){
            case "1":screen=$("screen_one");break;
            case "2":screen=$("screen_two");break;
            case "3":screen=$("screen_three");break;
            case "4":screen=$("screen_four");break;
        }
        screen.innerHTML = "<td>飞船"+signal.id+"号</td>"+"<td>"+signal.engine+"</td>"+"<td>"+signal.supply+"</td>"
        +"<td>"+signal.state+"</td>"+"<td>"+signal.power+"</td>";
    }
}

是时候展现我的画伯技术了


最终代码

最终代码
demo