设计模式

一、单例模式

不透明单例

var Singleton = function(name) {
    this.name = name;
    this.instance = null;
};
Singleton.prototype.getName = function(name) {
    alert(this.name);
};
Singleton.getInstance = function(name) {
    if(!this.instance) {
        this.instance = new Singleton(name);
    }
    return this.instance;
};
var a = Singleton.getInstance('tete1');
var b = Singleton.getInstance('tete2');

or

var Singleton = function(name) {
    this.name = name;
};
Singleton.prototype.getName = function() {
    alert(this.name);
};
Singleton.getInstance = (function(name) {
    var instance = null;
    return function(name){
        if(!instance) {
            instance = new Singleton(name);
        }
        return instance;
    }
})();
var a = Singleton.getInstance('test1');
var b = Singleton.getInstance('test2');
alert(a===b);

透明单例

var CreateDiv = (function() {
    var instance;
    var CreateDiv = function(html){
        if(instance) {return instance;}
        this.html = html;
        this.init();
        return instance = this;
    };
    CreateDiv.prototype.init = function() {
        var div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild(div);
    };
    return CreateDiv;
})();
var a = new CreateDiv('seve1');
var b = new CreateDiv('seve2');
alert(a===b);

用代理实现单例模式

var CreateDiv = function(html){
    this.html = html;
    this.init();
};
CreateDiv.prototype.init = function() {
    var div = document.createElement('div');
    div.innerHTML = this.html;
    document.body.appendChild(div);
};
var ProxySingletonCreateDiv = (function() {
    var instance;
    return function(html) {
        if(!instance) {
            instance = new CreateDiv(html);
        }
        return instance;
    }
})();
var a = new ProxySingletonCreateDiv('seve1');
var b = new ProxySingletonCreateDiv('seve2');
alert(a===b);

惰性单例

var createLoginLayer = (function() {
    var div;
    return function() {
        if(!div){
            div = document.createElement('div');
            div.innerHTML = '我是登录浮窗';
            div.style.display = 'none';
            document.body.appendChild(div);
        }
        return div;
    }
})();
document.getElementById('loginBtn').onclick = function() {
    var loginLayer = createLoginLayer();
    loginLayer.style.display = 'block';
};

通用的惰性单例

var getSingle = function(fn){
    var result;
    return function(){
        return result || (result = fn.apply(this, arguments));
    };
};
//创建浮窗
var
createLoginLayer = function() { var div = document.createElement('div'); div.innerHTML = '我是登录浮窗'; div.style.display = 'none'; document.body.appendChild(div); return div; }; var createSingleLoginLayer = getSingle(createLoginLayer); document.getElementById('loginbtn').onclick = function() { var loginLayer = createSingleLoginLayer(); loginLayer.style.display = 'block'; };
//创建iframe动态加载第三方页面
var createSingleIframe = getSingle(function() {
  var iframe = document.createElement('iframe');
  document.body.append(iframe);
  return iframe;
});
document.getElementById('loginbtn').onclick = function() {
  var loginLayer = createSingleIframe();
  loginLayer.src = 'http://knightboy.cn';
};

//给渲染列表绑定click事件 | //jQuery表示
var bindEvent = getSingle(function() { |var bindEvent = function() {
  document.getElementById('div1').onclick = function(){ $('div').one('click',function(){
    alert('click'); alert('click');
  } });
  return true; };
});

var render = function() {
  console.log('开始渲染列表');
  bindEvent();
};
render();
render();
render();

 二、发布订阅模式

//发布订阅模式的通用实现
var event = {
    clientList: [],
    listen: function(key, fn){
       if(!this.clientList[key]){
          this.clientList[key] = [];
       }
       this.clientList[key].push(fn);
    },
    trigger: function(){
       var key = Array.prototype.shift.call(arguments),
           fns = this.clientList[key];
       if(!fns || fns.length === 0) return false;
       for(var i=0,fn;fn = fns[i++];){
          fn.apply(this, arguments);
       }
    },
    remove: function(key, fn){
        var fns = this.clientList[key];
        if(!fns) return false;
        if(!fn)
            fns&&(fns.length === 0);
        else {
            for(var l=fns.length-1;l>=0;l--) {
                var _fn = fns[l];
                if(_fn===fn)
                    fns.splice(l,1);
            }
        }
    }
};
var salesOffices = {};
var installEvent = function(obj){
    for(var i in event){
       obj[i] = event[i];
    }
};
installEvent(salesOffices);
salesOffices.listen('squareMeter88', fn1=function(price){
    console.log('价格= ' + price);
});
salesOffices.listen('squareMeter88', fn2=function(price){
    console.log('价格= ' + price);
});
salesOffices.remove('squareMeter88',fn1);
salesOffices.trigger('squareMeter88',2000000);

 全局的发布订阅对象

var Event = (function() {
    var clientList = {},
        listen,
        trigger,
        remove;
    listen = function(key, fn){
       if(!clientList[key]){
          clientList[key] = [];
       }
       clientList[key].push(fn);
    };
    trigger = function(){
       var key = Array.prototype.shift.call(arguments),
           fns = clientList[key];
       if(!fns || fns.length === 0) return false;
       for(var i=0,fn;fn = fns[i++];){
          fn.apply(this, arguments);
       }
    };
    remove = function(key, fn){
        var fns = clientList[key];
        if(!fns) return false;
        if(!fn)
            fns&&(fns.length === 0);
        else {
            for(var l=fns.length-1;l>=0;l--) {
                var _fn = fns[l];
                if(_fn===fn)
                    fns.splice(l,1);
            }
        }
    };
    return {
        listen: listen,
        trigger: trigger,
        remove: remove
    }
})();

Event.listen('squareMeter88', function(price){
    console.log('价格= ' + price);
});
Event.trigger('squareMeter88',2000000);
//价格= 2000000

 全局事件的命名冲突处理

var Event = (function(){
    var global = this,
        Event,
        _default = 'default';
    Event = function(){
        var _listen,
            _trigger,
            _remove,
            _slice = Array.prototype.slice,
            _shift = Array.prototype.shift,
            _unshift = Array.prototype.unshift,
            namespaceCache = {},
            _create,
            find,
            each = function(ary, fn){
                var ret;
                for(var i=0, l=ary.length;i<l;i++) {
                    var n = ary[i];
                    ret = fn.call(n,i,n);
                }
                return ret;
            };
        _listen = function(key, fn, cache){
            if(!cache[key]) {
                cache[key]=[];
            }
            cache[key].push(fn);
        };
        _remove = function(key, cache, fn){
            if(cache[key]){
                if(fn){
                    for(var i=cache[key].length;i>=0;i--){
                        if(cache[key][i] === fn){
                            cache[key].splice(i, 1);
                        }
                    }
                }else{
                    cache[key] = [];
                }
            }
        };
        _trigger = function(){
            var cache = _shift.call(arguments),
                key = _shift.call(arguments),
                args = arguments,
                _self = this,
                ret,
                stack = cache[key];
            if(!stack || !stack.length){
                return;
            }
            return each(stack, function(){
                return this.apply(_self, args);
            });
        };
        _create = function(namespace){
            var namespace = namespace || _default;
            var cache = {},
                offlineStack = [], //离线事件
                ret = {
                    listen: function(key, fn, last){
                        _listen(key, fn, cache);
                        if(offlineStack === null){
                            return;
                        }
                        if(last === 'last') {
                            offlineStack.length && offlineStack.pop()();
                        }else{
                            each(offlineStack, function(){
                                this();
                            });
                        }
                        offlineStack = null;
                    },
                    one: function(key, fn, last){
                        _remove(key, cache);
                        this.listen(key, fn, last);
                    },
                    remove: function(key, fn,){
                         _remove(key, cache, fn);
                    },
                    trigger: function(){
                        var fn,
                            args,
                            _self = this;
                           _unshift.call(arguments, cache);
                        args = arguments;
                        fn = function(){
                            return _trigger.apply(_self, args);
                        };
                        if(offlineStack)
                            return offlineStack.push(fn);
                        return fn();
                    }
                };
                return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;
        };
        return {
            create: _create,
            one: function(key, fn, last){
                var event = this.create();
                event.one(key, fn, last);
            },
            remove: function(key, fn){
                var event = this.create();
                event.remove(key, fn);
            },
            listen: function(key, fn, last){
                var event = this.create();
                event.listen(key, fn, last);
            },
            trigger: function(){
                var event = this.create();
                event.trigger.apply(this,arguments);
            }
        };
    }();
    return Event;
})();
/*************先发布后订阅****************/
Event.trigger('click', 1);

 Event.listen('click', function(a){
  console.log(a);//1
 });

  /*************使用命名空间***************/

 Event.create('namespace1').listen('click', function(a){
  console.log(a); //1
 })

 Event.create('namespace1').trigger('click', 1)


 Event.create('namespace2').listen('click', function(a){
  console.log(a); //2
 })

 Event.create('namespace2').trigger('click', 2)

 

 三、享元模式

var Upload = function(uploadType) {
  this.uploadType = uploadType;
};
Upload.prototype.delFile = function(id) {
  uploadManager.setExternalState(id, this);
  if (this.fileSize < 3000) {
    return this.dom.parentNode.removeChild(this.dom);
  }
  if (window.confirm("确定要删除吗? " + this.fileName)) {
    return this.dom.parentNode.removeChild(this.dom);
  }
};
var UploadFactory = (function() {
  var createdFlyWeightObjs = {};
  return {
    create: function(uploadType) {
      if (createdFlyWeightObjs[uploadType]) {
        return createdFlyWeightObjs[uploadType];
      }
      return (createdFlyWeightObjs[uploadType] = new Upload(uploadType));
    }
  };
})();
var uploadManager = (function() {
  var uploadDatabase = {};
  return {
    add: function(id, uploadType, fileName, fileSize) {
      var flyWeightObj = UploadFactory.create(uploadType);
      var dom = document.createElement("div");
      dom.innerHTML =
        "<span>文件名称: " +
        fileName +
        ", 文件大小: " +
        fileSize +
        "</span>" +
        '<button class="delFile">删除</button>';
      dom.querySelector(".delFile").onclick = function() {
        flyWeightObj.delFile(id);
      };0
      document.body.appendChild(dom);
      uploadDatabase[id] = {
        fileName: fileName,
        fileSize: fileSize,
        dom: dom
      };
      return flyWeightObj;
    },
    setExternalState: function(id, flyWeightObj) {
      var uploadData = uploadDatabase[id];
      for (var i in uploadData) {
        flyWeightObj[i] = uploadData[i];
      }
    }
  };
})();

var id = 0;
window.startUpload = function(uploadType, files) {
  for (var i = 0, file; (file = files[i++]); ) {
    var uploadObj = uploadManager.add(
      ++id,
      uploadType,
      file.fileName,
      file.fileSize
    );
  }
};

startUpload("plugin", [
  {
    fileName: "1.txt",
    fileSize: 1000
  },
  {
    fileName: "2.html",
    fileSize: 3000
  },
  {
    fileName: "3.txt",
    fileSize: 5000
  }
]);
startUpload("flash", [
  {
    fileName: "4.txt",
    fileSize: 1000
  },
  {
    fileName: "5.html",
    fileSize: 3000
  },
  {
    fileName: "6.txt",
    fileSize: 5000
  }
]);

 

posted @ 2018-08-07 17:27  Princess_Knight  阅读(81)  评论(0编辑  收藏  举报