javascript设计模式

以下代码在ie6&ie6+&chrome测试通过,code地址:

https://code.csdn.net/liuyanzhi08/javascript_design_pattern/tree/master 

 

1.单例模式(Singleton):

<html><head><title>Singleten-单例模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在singleten模块
  MyNamespace.singleten = (function(){
    var appid =  'helloJs';
    return {
      getAppId:function(){
        return appid;
      }
    };
  })();
  console.log(MyNamespace.singleten.getAppId());
  </script>
</body>
</html>

  

 
2.工厂模式(Factory)
<html><head><title>Factory-工厂模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在xhr模块 ,xhr其实就是一个工厂,生产函数是getXHR
  MyNamespace.xhr = (function(){
    return {
      getXHR:function(){
        methods = [
          function(){ return new XMLHttpRequest(); },
          function(){ return new ActiveXObject('Microsoft.XMLHTTP'); },
          function(){ return new ActiveXObject('Msxml2.XMLHTTP'); }
        ]
        for(var i = 0; i < methods.length; i++){
          try{
            methods[i]();
          }catch(e){
            continue;
          }
          this.getXHR = methods[i]();
          return methods[i]();
        }	
      }
    }
  })();

  alert(MyNamespace.xhr.getXHR());
  </script>
</body>
</html>

  

3.桥接模式(Bridge)
<html><head><title>Bridge-桥接模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在request模块 
  MyNamespace.request = (function(){
    function getXHR(){
      methods = [
        function(){ return new XMLHttpRequest(); },
        function(){ return new ActiveXObject('Microsoft.XMLHTTP'); },
        function(){ return new ActiveXObject('Msxml2.XMLHTTP'); }
      ]
      for(var i = 0; i < methods.length; i++){
        try{
          methods[i]();
        }catch(e){
          continue;
        }
        this.getXHR = methods[i]();
        return methods[i]();
      }	
    }
    function handleReadystate(xhr, callback){
      xhr.onreadystatechange = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
          if(callback){
            callback(xhr.responseText);
          }
        }
      }

    }	
    return function(method, uri, postData, callback){
      //此处运用了桥接模式
      var xhr = getXHR();
      xhr.open(method, uri, true);
      handleReadystate(xhr, callback);
      xhr.send(postData || null);
    }
  })();

  MyNamespace.request('post', 'test.php', "name=test&pwd=test", function(data){
    alert(data);
  })
  </script>
</body>
</html>

  

4.组合模式(Composite)
<html><head><title>Composite-组合模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在form模块
  MyNamespace.form = (function(){
    function Form(id, method, action){
      this.element = document.createElement('form');
      this.element.id = id;
      this.element.method = method;
      this.element.action = action;
      this.store = [];
    }
    Form.prototype = {
      add: function(fieldset){
        this.element.appendChild(fieldset.getDom());
        this.store.push(fieldset);
      },
      getDom: function(){
        return this.element;
      }
    }
    function Field(id){
      this.element = document.createElement('fieldset');
      this.element.id = id;
      this.store = [];
    }
    Field.prototype = {
      add: function(input){
        this.element.appendChild(input.getDom());
        this.store.push(input);
      },
      getDom: function(){
        return this.element;
      }
    }
    function Input(id, type, label){
      this.wrapper =  document.createElement('div');

      var labelTextNode = document.createTextNode(label);
      this.label = document.createElement('label');
      this.label.appendChild(labelTextNode);
      this.wrapper.appendChild(this.label);
    
      this.element = document.createElement(type);
      this.element.id = id;
      this.wrapper.appendChild(this.element);
    }
    Input.prototype = {
      getDom: function(){
        return this.wrapper;
      }
    }
    return{
      Form:Form,
      Field:Field,
      Input:Input
    }
  })();
  window.onload = function(){
      var form = new MyNamespace.form.Form('myForm', 'post', 'test.php');
      var fields = [
        new MyNamespace.form.Field('field1'),
        new MyNamespace.form.Field('field2'),
        new MyNamespace.form.Field('field3')
      ];
      var inputs = [
        [
          new MyNamespace.form.Input('input1', 'input', 'input1:'),
          new MyNamespace.form.Input('input2', 'textarea', 'input2:'),
          new MyNamespace.form.Input('input3', 'input', 'input3:')
        ],
        [
          new MyNamespace.form.Input('input4', 'textarea', 'input4:'),
          new MyNamespace.form.Input('input5', 'input', 'input5:'),
          new MyNamespace.form.Input('input6', 'input', 'input6:')
        ],
        [
          new MyNamespace.form.Input('input7', 'input', 'input7:'),
          new MyNamespace.form.Input('input8', 'input', 'input8:'),
          new MyNamespace.form.Input('input9', 'textarea', 'input9:')
        ]

      ]
      for(var i = 0; i < fields.length; i++){
        form.add(fields[i]);
        for(var j = 0; j < inputs.length; j++){
          fields[i].add(inputs[i][j]);
        }
      }
      
      document.getElementsByTagName('body')[0].appendChild(form.getDom());
  }

  </script>
</body>
</html>

  

5.门面模式(Facade)
<html><head><title>Facade-门面模式</title><meta charset="utf-8"></head>
<body>
  <p id="greeting">Hello js!</p>
  <p id="greeting1">Hello js1!</p>

  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在even模块
  MyNamespace.event = (function(){
    return {
      setStyle: function(ids, prop, value){
        for(var i = 0; i < ids.length; i++){
          document.getElementById(ids[i]).style[prop] = value;
        }
      },
      setCss: function(ids, styles){
        for(var prop in styles){
          if(!styles.hasOwnProperty(prop)){
            continue;
          }else{
            this.setStyle(ids, prop, styles[prop]);
          }
        }
      }
    }
  })();

  MyNamespace.event.setCss(['greeting', 'greeting1'], {
    'color': 'red',
    'background': 'green'
  })
  </script>
</body>
</html>

  

 
6.适配器模式(Adapter)
<html><head><title>Adapter-适配器模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在sample模块
  MyNamespace.sample = (function(){
    return {
      aFunctin: function(arg1, arg2, arg3){
        alert(arg1);
        alert(arg2);
        alert(arg3);
      },
      adapter: function(obj){
        var i = 0;
        var args = [];
        for(var prop in obj){
          if(!obj.hasOwnProperty(prop)) continue;
          args[i++] = obj[prop];
        }
        this.aFunctin(args[0], args[1], args[2]);
      }
    }
  })();

  // MyNamespace.sample.aFunctin('a', 'b', 'c');
  MyNamespace.sample.adapter({
    'arg1':'a',
    'arg2':'b',
    'arg3':'c'
  })
  </script>
</body>
</html>

  

7.装饰者模式(Decorator)
<html><head><title>Decorator-装饰者模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在sample模块
  MyNamespace.sample = (function(){
    function buildDom(){}
    buildDom.prototype = {
      startBuilt: function(){
        var body = document.getElementsByTagName('body')[0];
        for(var i = 0; i < 100; i++){
          var list = document.createElement('ul');
          for(var j = 0; j < 100; j++){
            var item = document.createElement('li');
            var text = document.createTextNode('test');
            item.appendChild(text);
            list.appendChild(item);
          }
          body.appendChild(list);
        }
      }
    }
    function timeDetector(buildDom){
      this.buildDom = buildDom;
      this.startTime;
    }
    timeDetector.prototype = {
      startRun: function(){
        this.startTime = (new Date()).getTime();
      },
      stopRun: function(){
        var runTime = (new Date()).getTime() - this.startTime;
        console.log("running cost:" + runTime + 'ms');
      },
      startBuilt: function(){
        this.startRun();
        this.buildDom.startBuilt();
        this.stopRun();
      }
    }
    return {
      buildDom: buildDom,
      timeDetector: timeDetector
    }
  })()

  window.onload = function(){
    var buildDom = new MyNamespace.sample.buildDom();
    var buildDom = new MyNamespace.sample.timeDetector(buildDom);
    buildDom.startBuilt();
  }
  </script>
</body>
</html>

  

8.享元模式(Flyweight)
<html><head><title>Flyweight-享元模式</title><meta charset="utf-8"></head>
<body>
  <style type="text/css">
    .month{ 200px;height:150px;padding:10px;border: 1px solid green; float: left;margin-right: 5px;margin-bottom: 5px;}
    .day{ 15px;border: 1px solid green;float: left;margin-right: 5px;margin-bottom: 5px;padding: 2px;text-align: center;}
  </style>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在calendar模块
  MyNamespace.calendar = (function(){
    function Day(){}
    Day.prototype = {
      getDom: function(num){
        var element = document.createElement('div');
        element.className = 'day';
        var text = document.createTextNode(num);
        element.appendChild(text);
        return element;
      }
    }
    var flyWeightDay = new Day();
    function Year(year, parent) {
      this.element;
      this.parent = parent;
      this.isLeapYear = !(year%400) || (!(year%4) && (year%100));
      this.months = [];
      for(var i = 0; i < 12; i++){
        this.months.push(new Month(i, this.isLeapYear));
      }

      this.buildDom();
    }
    Year.prototype = {
      buildDom: function(parent){
        this.element = document.createElement('div');
        this.element.className = 'year';
        for(var i = 0; i < this.months.length; i++){
          var month = this.months[i];
          month.buildDom();
          this.element.appendChild(month.getDom());
        }
        this.parent.appendChild(this.element);
      }

    }
    function Month(month, isLeapYear){
      this.days = [];
      this.element;
      this.numDay;
      switch(month){
        case 0:
          this.numDay = 31;
          break;
        case 1:
          this.numDay = isLeapYear?29:28;
          break;
        case 2:
          this.numDay = 31;
          break;
        case 3:
          this.numDay = 30;
          break;
        case 4:
          this.numDay = 31;
          break;
        case 5:
          this.numDay = 30;
          break;
        case 6:
          this.numDay = 31;
          break;
        case 7:
          this.numDay = 31;
          break;
        case 8:
          this.numDay = 30;
          break;
        case 9:
          this.numDay = 31;
          break;
        case 10:
          numDay = 30;
          break;
        case 11:
          this.numDay = 31;
          break;
      }			
    }
    Month.prototype = {
  buildDom: function(){
this.element = document.createElement('div');
this.element.className = 'month';
for(var i = 0;  i < this.numDay; i++){
this.element.appendChild(flyWeightDay.getDom(i+1));
  }
  },
  getDom: function(){
return this.element;
  }
  }
return {
  Year:Year
  }
  })();

  window.onload = function(){
var body = document.getElementsByTagName('body')[0];
new MyNamespace.calendar.Year(2004, body);
  }

/******************************************************
   * 非享元版:使用了几百个Day对象,占用内存很大
   ***************************************/

// var MyNamespace = window.MyNamespace || {};
// // 定义在calendar模块
// MyNamespace.calendar = (function(){
// 	function Year(year, parent) {
// 		this.element;
// 		this.parent = parent;
// 		this.isLeapYear = !(year%400) || (!(year%4) && (year%100));
// 		this.months = [];
// 		for(var i = 0; i < 12; i++){
// 			this.months.push(new Month(i, this.isLeapYear));
// 		}

// 		this.buildDom();
// 	}
// 	Year.prototype = {
// 		buildDom: function(parent){
// 			this.element = document.createElement('div');
// 			this.element.className = 'year';
// 			for(var i = 0; i < this.months.length; i++){
// 				var month = this.months[i];
// 				month.buildDom();
// 				this.element.appendChild(month.getDom());
// 			}
// 			this.parent.appendChild(this.element);
// 		}

// 	}
// 	function Month(month, isLeapYear){
// 		this.days = [];
// 		this.element;
// 		var numDay;
// 		switch(month){
// 			case 0:
// 				numDay = 31;
// 				break;
// 			case 1:
// 				numDay = isLeapYear?29:28;
// 				break;
// 			case 2:
// 				numDay = 31;
// 				break;
// 			case 3:
// 				numDay = 30;
// 				break;
// 			case 4:
// 				numDay = 31;
// 				break;
// 			case 5:
// 				numDay = 30;
// 				break;
// 			case 6:
// 				numDay = 31;
// 				break;
// 			case 7:
// 				numDay = 31;
// 				break;
// 			case 8:
// 				numDay = 30;
// 				break;
// 			case 9:
// 				numDay = 31;
// 				break;
// 			case 10:
// 				numDay = 30;
// 				break;
// 			case 11:
// 				numDay = 31;
// 				break;
// 		}
// 		for(var i = 1; i <= numDay; i++){
// 			this.days.push(new Day(i));
// 		}
// 	}
// 	Month.prototype = {
// 		buildDom: function(){
// 			this.element = document.createElement('div');
// 			this.element.className = 'month';
// 			for(var i = 0;  i < this.days.length; i++){
// 				var day = this.days[i];
// 				day.buildDom();
// 				this.element.appendChild(day.getDom());
// 			}
// 		},
// 		getDom: function(){
// 			return this.element;
// 		}
// 	}
// 	function Day(num){
// 		this.num = num;
// 		this.element;
// 	}
// 	Day.prototype = {
// 		buildDom: function(){
// 			this.element = document.createElement('div');
// 			this.element.className = 'day';
// 			var text = document.createTextNode(this.num);
// 			this.element.appendChild(text);
// 		},
// 		getDom: function(){
// 			return this.element;
// 		}
// 	}
// 	return {
// 		Year:Year
// 	}
// })();

// window.onload = function(){
// 	var body = document.getElementsByTagName('body')[0];
// 	new MyNamespace.calendar.Year(2004, body);
// }
</script>
</body>
</html>

  

9.代理模式(Proxy)
<html><head><title>Proxy-代理模式</title><meta charset="utf-8"></head>
<body>
  <style type="text/css">
    body{padding: :0;margin:0;overflow: hidden;font-family: "微软雅黑"}
    #modal-dialog{border: 3px solid green;padding: 10px;}
    #modal-close{position: absolute;top: -20px;right: -18px;cursor: pointer;border: 2px solid green;padding: 1px;border-radius:50% 50%; 15px;height: 15px;text-align: center;line-height: 12px;color: green;font-weight: bold;}
    #modal-loading{text-align: center;}
  </style>

  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在component模块
  MyNamespace.component = (function(){
    function Modal(option){
    }
    Modal.prototype = {
      _addListener: function(){
        var that = this;
        window.onresize =  function(){
          that._resizeMask();
          that._repositionDialog();
        }
        this.closeBtn.onclick = function(){
          that.mask.parentNode.removeChild(that.mask);
          that.dialog.parentNode.removeChild(that.dialog);
        }
      },
      _resizeMask: function(){
        this.mask.style.width = '100%';
        this.mask.style.height = document.body.clientHeight;
      },
      _repositionDialog: function(){
        this.dialog.style.left = (document.body.clientWidth-this.dialog.offsetWidth)/2;
        this.dialog.style.top = (document.body.clientHeight-this.dialog.offsetHeight)/3;
      },
      show: function(){
        var body = document.getElementsByTagName('body')[0];
        //mask
        this.mask = document.createElement('div');
        this.mask.id = 'modal-mask';
        this.mask.style.position = 'absolute';
        this.mask.style.left = 0;
        this.mask.style.top = 0;
        this.mask.style.background = '#000';
        this.mask.style.opacity = '0.5';
        this.mask.style.filter = 'alpha(opacity=50)';
        this._resizeMask();
        body.appendChild(this.mask);
        //diaglog
        this.dialog = document.createElement('div');
        this.dialog.innerHTML = 'HELLO MODAL!';
        this.dialog.id = 'modal-dialog';
        this.dialog.style.position = 'absolute';
        //close-button
        this.closeBtn = document.createElement('div');
        var closeText = document.createTextNode('x');
        this.closeBtn.id = 'modal-close';  
        this.closeBtn.appendChild(closeText);
        this.dialog.appendChild(this.closeBtn);

        body.appendChild(this.dialog);
        this._repositionDialog();

        this._addListener();
      }
    }
    function ModalProxy(){
      this.interval = null;
      this.modal = new Modal();
      this._initialize();
    }
    ModalProxy.prototype = {
      _removeLoading: function(){
        this.mask.parentNode.removeChild(this.mask);
        this.loading.parentNode.removeChild(this.loading);
      },
      _resizeMask: function(){
        this.mask.style.width = '100%';
        this.mask.style.height = document.body.clientHeight;
      },
      _repositionLoading: function(){
        this.loading.style.left = (document.body.clientWidth-this.loading.offsetWidth)/2;
        this.loading.style.top = (document.body.clientHeight-this.loading.offsetHeight)/3;
      },
      _initialize: function(){
        var that = this;
        var body = document.getElementsByTagName('body')[0];
        //mask
        this.mask = document.createElement('div');
        this.mask.id = 'modal-loading-mask';
        this.mask.style.position = 'absolute';
this.mask.style.left = 0;
this.mask.style.top = 0;
this.mask.style.background = '#000';
this.mask.style.opacity = '0.5';
this.mask.style.filter = 'alpha(opacity=50)';
this._resizeMask();
this.num = 0;
  body.appendChild(this.mask);
//loading text
this.loading = document.createElement('div');
this.loading.innerHTML = 'loading...';
this.loading.id = 'modal-loading';
this.loading.style.position = 'absolute';

  body.appendChild(this.loading);
this._repositionLoading();
  window.onresize =  function(){
  that._resizeMask();
  that._repositionLoading();
  }

this.interval = setTimeout(function(){
  that._checkInitailization();
  }, 100);
  },
  _checkInitailization: function(callback){
var that = this;
this.num++;
//这里用num++ 来模拟等待数据处理的过程. this.num > 20为loading停止条件
if(this.num > 20){
  clearTimeout(this.interval);
this._removeLoading();
  callback();
  }else{
  document.title =  this.num;
this.interval = setTimeout(function(){
  that._checkInitailization(callback)
  }, 100);					
  }
  },
  show: function(){
var that = this;
this._checkInitailization(function(){
  that.modal.show();

  });	
  }
  }
return {
  ModalProxy:ModalProxy
  }
  })();

  window.onload = function(){
var mp = new MyNamespace.component.ModalProxy();

  mp.show();

  }
</script>


  1. Singleton - 单例模式<br/>
  2. Factory   - 工厂模式<br/>
  3. Bridge    - 桥接模式<br/>
  4. Composite - 组合模式<br/>
  5. Facade	 - 门面模式<br/>
  6. Adapter   - 适配器模式<br/>
  7. Decorator - 装饰者模式<br/>
  8. Flyweight - 享元模式<br/>
  9. Proxy	 - 代理模式<br/>
</body>
</html>

  

10.观察者模式(Observer)
<html><head><title>Observer-观察者模式</title><meta charset="utf-8"></head>
<body>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在sample模块 
  MyNamespace.sample = (function(){
    function Publisher(){
      this.subscribers = [];
    }
    Publisher.prototype = {
      publish: function(msg){
        for(var i in this.subscribers){
          this.subscribers[i].msg = msg;
        }
        alert('Publish:"'+msg+'"');
      }
    }
    function Subscriber(name){
      this.name = name;
      this.msg;
    }
    Subscriber.prototype = {
      subscribe: function(publisher){
        for(var i in publisher.subscribers){
          if(publisher.subscribers[i] == this){
            return;
          }
        }
        publisher.subscribers.push(this);
      },
      getMsg: function(){
        alert(this.name + ' has receive:"' + this.msg + '"');
      }
    }
    return {
      Publisher:Publisher,
      Subscriber:Subscriber
    }
  })();

  var p = new MyNamespace.sample.Publisher();
  var s1 = new MyNamespace.sample.Subscriber('s1');
  var s2 = new MyNamespace.sample.Subscriber('s2');
  var s3 = new MyNamespace.sample.Subscriber('s3');

  s1.subscribe(p);
  s2.subscribe(p);
  s3.subscribe(p);

  p.publish('new report');
  s1.getMsg();
  s2.getMsg();
  s3.getMsg();

  p.publish('another report')
  s1.getMsg();
  s2.getMsg();
  s3.getMsg();

  </script>
</body>
</html>

  

11.命令模式(Command)
<html><head><title>Command-命令模式</title><meta charset="utf-8"></head>
<body>
  <style type="text/css">
  .memu{}
  .menu-item{padding: 5px 10px; background: green; 100px;cursor: pointer;margin-bottom: 1px;}
  </style>
  <script type="text/javascript">
  var MyNamespace = window.MyNamespace || {};
  // 定义在composite模块 
  MyNamespace.composite = (function(){
    function Menu(parent){
      this.parent = parent;
      this.element = document.createElement('div');
      this.element.className = 'menu';
      this.parent.appendChild(this.element);
    }
    Menu.prototype = {
      add: function(menuItem){
        this.element.appendChild(menuItem.element);
      }
    }
    function MenuItem(name, command){
      this.element = document.createElement('div');
      this.element.className = 'menu-item';
      var itemName = document.createTextNode(name)
      this.element.appendChild(itemName);
      this.command = command;
      this._addAction();
    }
    MenuItem.prototype = {
      _addAction: function(){
        var that = this;
        this.element.onclick = function(){
          that.command.run();
        }
      }
    }
    function Command(name){
      this.name = name;
    }
    Command.prototype = {
      run: function(){
        alert(this.name);
      }
    }
    return {
      Menu: Menu,
      MenuItem: MenuItem,
      Command: Command
    }
  })();

  window.onload = function(){
    var body = document.getElementsByTagName('body')[0];
    var menu = new MyNamespace.composite.Menu(body);
    var editCommand = new MyNamespace.composite.Command('edit');
    var saveCommand = new MyNamespace.composite.Command('save');
    var menuItem = new MyNamespace.composite.MenuItem('选项一', editCommand);
    var menuItem1 = new MyNamespace.composite.MenuItem('选项二', saveCommand);
    menu.add(menuItem);
    menu.add(menuItem1);
  }

  </script>
</body>
</html>

  

原文地址:https://www.cnblogs.com/zhuyang/p/4321033.html