十道前端面試題第【05】篇

1、工廠模式(Factory Pattern)

// 籃球基類
var Basketball = function(){
    this.info = '籃球流行於美國';
};
Basketball.prototype = {
    getMeber : function(){
        console.log('每個隊有5名球員');
    },
    getBallSize: function(){
        console.log('5號球');
    }
};

// 足球基類
var Football = function(){
    this.info = '足球流行於巴西';
};
Football.prototype = {
    getMeber: function(){
        console.log('每隊有11名球員');
    },
    getBallSize: function(){
        console.log('7號球');
    }
};

// 網球基類
var Tennis = function(){
    this.info = '網球流行於法國';
};
Tennis.prototype = {
    getMeber: function(){
        console.log('每隊只有1名球員');
    },
    getBallSize: function(){
        console.log('11號球');
    }
};

// 簡單工廠模式:‘運動工廠’,它會幫你找到籃球、足球和網球等
var SportFactory = function(name){
    switch(name){
        case 'NBA':
            return new Basketball();
        case 'worldCup':
            return new Football();
        case 'FrenchOpen':
            return new Tennis();
    };
};

// 測試
var football = SportFactory('worldCup');
console.log(football);
console.log(football.info);
console.log(football.getBallSize());


2、單例模式(Singleton Pattern)

// 單例的延遲創建、惰性創建 
var LazySingle = (function(){
    // 單例實例的引用
    var _instance = null;
    // 單例
    function Single(){
        return {
            publicMethod: function(){},
            publicProperty: '1.0'
        }
    }
    // 延遲創建單例
    return function(){
        if(!_instance){
            _instance = Single();
        }
        return _instance;
    }
})();

// 測試
console.log(LazySingle().publicProperty);


3、原型模式(Prototype Pattern)

// 基類
var LoopImages = function(imgArr,container){
    this.imagesArray = imgArr;
    this.container = container;
}
// 把基類中的方法提取出來,放到原型鏈中去
LoopImages.prototype = {
    createImage: function(){
      console.log('LoopImages');
    },
    changeImage: function(){
      console.log('切換');
    }
}

// 封裝上下滑動的輪播類,並覆寫changeImage()方法
var SlideLoopImg = function(imgArr,container){
    LoopImages.call(this,imgArr,container);
}
SlideLoopImg.prototype = new LoopImages();
SlideLoopImg.prototype.changeImage = function(){
    console.log('上下切換');
}

// 封裝漸隱切換的輪播類,並覆寫changeImage()方法
var FadeLoopImg = function(imgArr,container,arrow){
    LoopImages.call(this,imgArr,container);
}
FadeLoopImg.prototype = new LoopImages();
FadeLoopImg.prototype.changeImage = function(){
    console.log('漸隱切換');
}

// 對輪播基類的擴展,子類可以共享到這些擴展
LoopImages.prototype.getImageLength = function(){
    return this.imagesArray.length;
}

// 擴展漸隱輪播類。對子類擴展,不影響同級的子類
FadeLoopImg.prototype.getContainer = function(){
    return this.container;
}


4、建造者模式(Builder Pattern)

// 人的相關描述
var Human = function(param){
    this.skill = param && param.skill || '保密';
    this.hobby = param && param.hobby || '保密';
}

Human.prototype = {
    getSkill: function(){
        return this.skill;
    },
    getHobby: function(){
        return this.hobby;
    }
}

// 人的姓名
var Named = function(name){
    var that = this;
    (function(name,that){
        that.wholeName = name;
        if(name.indexOf(' ') > -1){
            that.FirstName = name.slice(0,name.indexOf(' '));
            that.SecondName = name.slice(name.indexOf(' '));
        }
    })(name,that);
}

// 人的職業及職業描述
var Work = function(work){
    var that = this;
    (function(work,that){
        switch(work){
            case 'code':
                that.work = '工程師';
                that.workDescript = '每天沉醉於編程';
                break;
            case 'UI':
            case 'UE':
                that.work = '設計師';
                that.workDescript = '設計更像一種藝術';
                break;
            case 'teach':
                that.work = '老師';
                that.workDescript = '分享也是一種快樂';
                break;
        }
    })(work,that);
}

Work.prototype.changeWork = function(work){
    this.work = work;
}

Work.prototype.changeDescript = function(setence){
    this.workDescript = setence;
}

// 建造者模式:用3個類組合調用,創建出一個完整的Person類
// Person類由 Human / Named / Work 三個類組合而成
var Person = function(name,work){
    var _person = new Human();
    // 關注對象創建的細節和過程
    _person.name = new Named(name);
    _person.work = new Work(work);
    return _person;
}

// 測試
var person = new Person('xiao ming', 'code');

console.log(person.skill);
console.log(person.name.FirstName);
console.log(person.work.work);
console.log(person.work.workDescript);
person.work.changeDescript('更改一下職位描述');
console.log(person.work.workDescript);


5、外觀模式(Facade Pattern)

// 外觀模式
function addEvent(dom,type,fn){
    if(dom.addEventListener){
        dom.addEventListener(type,fn,false);
    }else if(dom.attachEvent){
        dom.attachEvent('on'+type,fn);
    }else{
        dom['on'+type] = fn;
    }
}

// 測試
addEvent(document, 'click', function(){
    console.log('11');
});
addEvent(document, 'click', function(){
    console.log('22');
});


6、享元模式(Flyweight Pattern)

var FlyWeight = {
    moveX: function(x) {
        this.x = x;
    },
    moveY: function(y) {
        this.y = y;
    }
}

var Player = function(x, y, color) {
    this.x = x;
    this.y = y;
    this.color = color;
}
Player.prototype = FlyWeight;
Player.prototype.changeColor = function(color) {
    this.color = color;
}

// 讓精靈繼承移動的方法
var Spirit = function(x, y, r) {
    this.x = x;
    this.y = y;
    this.r = r;
}
Spirit.prototype = FlyWeight;
Spirit.prototype.changeR = function(r) {
    this.r = r;
}


7、組合模式(Composite Pattern)

var oForm = new FormItem('form-item', document.body);

oForm.add(
    new FieldsetItem('account', '賬號').add(
        new Group().add(
            new LabelItem('user-name', '用戶名:')
        ).add(
            new InputItem('user-name')
        ).add(
            new SpanItem('4到6位數字或字母')
        )
    ).add(
        new Group().add(
            new LabelItem('user-password', '密碼:')
        ).add(
            new InputItem('user-password')
        ).add(
            new SpanItem('6位12位數字或者密碼')
        )
    )
).add(
    // ...
).show();


8、適配器模式(Adapter Pattern)

// 庫B的源碼如下:
var B = B || {};
B.g = function(id){
    return document.getElementById(id);
};
B.on = function(id,type,fn){
    var dom = typeof if === 'string' ? this.g(id) : id;
    if(dom.addEventListener){
        dom.addEventListener(type,fn,false);
    }else if(dom.attachEvent){
        dom.attachEvent('on'+type,fn);
    }else{
        dom['on'+type] = fn;
    }
}

// 適配器模式,把B框架轉換成jQuery,並覆寫B庫的兩個方法
window.B = B = jQuery;

B.g = function(id){
    return $(id).get(0);
}
B.on = function(id,type,fn){
    var dom = typeof id === 'string' ? $('#'+id) : $(id);
    dom.on(type,fn);
}


9、中介者模式(Mediator Pattern)

// 中介者模式
var Mediator = function() {
  // 消息對象
  var _msg = {};
  return {
    // 註冊:向指定類型中追加新的功能方法
    register: function(type, action) {
      if (_msg[type]) {
        _msg[type].push(action);
      } else {
        _msg[type] = [];
        _msg[type].push(action);
      }
    },
    // 發佈:調用指定類型中的功能方法集
    send: function(type) {
      if (_msg[type]) {
        for (var i=0; i<_msg[type].length; i++) {
          _msg[type][i] && _msg[type][i]();
        }
      }
    }
  }
}();


10、觀察者模式(Observer Pattern)

// 把觀察者放在閉包中,當頁面加載時就立即執行
var Observer = (function() {
    // 防止消息隊列暴露而被篡改,因此我們要把消息容器作爲靜態私有變量
    var _messages = {};
    return {
        // 註冊訂閱
        regist: function(type, fn) {
            if (typeof _messages[type] === 'undefined') {
                // 如果此消息不存在,則創建一個新的消息類型,並把消息放入到隊列中去
                _messages[type] = [fn];
            } else {
                // 如果此消息存在,直接把消息追加到隊列中去
                _messages[type].push(fn);
            }
        },
        // 消息發佈
        fire: function(type, args) {
            if(!_messages[type]) return;
            // 定義消息信息
            var events = {
                type: type,
                args: args || {}
            };
            for (var i=0; i<_messages[type].length; i++) {
                // 依次執行註冊的消息對應的動作序列
                _messages[type][i].call(this, events);
            }
        },
        // 取消訂閱
        remove: function(type) {
            if (_messages[type] instanceof Array) {
                for (var i=_messages[type].length-1; i>=0; i--) {
                    // 如果存在該動作則從消息動作序列中移除相應動作
                     _messages[type].splice(i, 1);
                }
            }
        }
    }
})();

// 訂閱一條消息
Observer.regist('test', function(e) {
    console.log(e.type, e.args.msg);
});

// 發佈消息
Observer.fire('test', {msg: '傳遞參數'});


本週結束,下週繼續!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章