十道前端面试题第【05】篇

2021-05-18  本文已影响0人  夏海峰

摘要:本篇是设计模式专题,分享了10个设计模式的JS示例代码——工厂模式、单例模式、原型模式、建造者模式、外观模式、享元模式、组合模式、适配器模式、中介者模式、观察者模式。

学习资源推荐JS设计模式文集图说设计模式一句话归纳设计模式



面试题

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: '传递参数'});

本周结束,下周继续!!!

上一篇 下一篇

猜你喜欢

热点阅读