JS设计模式——封装与对象

封装

封装目的

  • 定义变量不会污染外部
  • 能够作为一个模块调用
  • 遵循开闭原则

什么是好的封装

  1. 变量外部不可见
  2. 调用接口使用
  3. 留出扩展接口

封装对象时的三种设计模式

创建一个对象的模式

工厂模式

目的:方便我们大量创建对象

应用场景:当某一个对象需要经常创建的时候

例:如分页器,提示窗

基本结构

// 工厂模式就是写一个封装了大量对象的方法,只需调用这个方法,就能拿到你要的对象
function Factory(type) {
    switch (type) {
      case 'type1':
        return new Type1();
      case 'type2':
        return new Type2();
      case 'type3':
        return new Type3();
    }
}

示例(多彩弹窗,JQ源码)

// 多彩的弹窗
// 需求:项目有一个弹窗需求,弹窗有多种,他们之间存在内容和颜色上的差异
// 工厂模式1.0
(function(){
    //信息弹窗
    function infoPop(){
    }
    // 确认弹窗
    function confirmPop(){
    }
    // 取消弹窗
    function cancelPop(){
    }
    function pop(type,content,color){
        // 如果new pop()
        if(this instanceof pop) {
            var s = new this[type](content, color);       
        } else {
            return new pop(type, content, color);        
        }
        switch(type) {
          case 'infoPop':
          return new infoPop(content,color);
          case 'confirmPop':
          return new confirmPop(content,color);
          case 'cancelPop':
          return new cancelPop(content,color);
        }
    }
    window.pop = pop;
})()
// 工厂模式2.0
(function(){
    function pop(type,content,color){
        // 如果new pop();健壮性
        if(this instanceof pop) {
            var s = new this[type](content, color);   
            return s;    
        } else {
            return new pop(type, content, color);        
        }
    }
    // 可扩展性
    pop.prototype.infoPop=function(){
      console.log('infoPop');
    }
    pop.prototype.confirmPop=function(){
        
    }
    pop.prototype.cancelPop=function(){
        
    }
    window.pop = pop;
})()
pop('infoPop', 'hello', 'red');
// 源码示例-jquery
// 需求:jQuery需要操作dom,每一个dom都是一个jq对象
(function(){
    var jQuery = function( selector, context ) {
        // 此处如果new jQuery();会产生递归,无限循环
        return new jQuery.fn.init( selector, context);
    }
    jQuery.fn=jQuery.prototype={ // 让fn=原型链
        init:function(){
            
        }
    }
    jQuery.fn.init.prototype = jQuery.fn; // 让jQuery.fn.init的原型链 = fn = jQuery的原型链
    jQuery.extend = jQuery.fn.extend = function() {// JQ的拷贝扩展
    }
    jQuery.extend({
    });
    window.$ = window.jQuery = jQuery;
})()

建造者模式

目的:需要组合出一个全局对象

应用场景:当要创建单个、庞大的组合对象时

例:如轮播图

// 把一个复杂的类各个部分,拆分成独立的类,然后再在最终类里组合到一块,final为最终给出去的类
// 模块1
function Mode1() {
    
}
// 模块2
function Mode2() {
    
}
// 最终的使用类
function Final() {
    this.mode1 = new Mode1();
    this.mode2 = new Mode2();
}

示例(编写一个编辑器插件、Vue的初始化)

// 编写一个编辑器插件
// 需求:有一个编辑器插件,初始化的时候需要配置大量参数,而且内部功能很多
//定义最终类
function Editor(){
    this.initer = new initHtml();
    this.fontControll = new fontControll();
    this.stateControll = new stateControll();
}
//html初始模块:样式,dom渲染
function initHtml(domStyle){
  this.template='<div style={{editorStyle}}><div></div><div><textarea style={{areaSyle}}/></div></div>';
}
initHtml.prototype.initStyle=function(){
}
initHtml.prototype.renderDom=function(){
}
//字体:颜色,大小
function fontControll(){
  
};
fontControll.prototype.changeColor=function(){
}
fontControll.prototype.changeFontsize=function(){
}
//状态:保存,回滚,前进
function stateControll(){
    this.state = [];
    this.nowstate = 0;
}
stateControll.prototype.saveState=function(){
}
stateControll.prototype.stateBack=function(){
    var state = this.state[this.nowstate - 1];
    this.fontControll.changeColor(state.color);
    this.fontControll.changeFontsize(state.color);
}
stateControll.prototype.stateGo=function(){
}
window.Editor=Editor;
// Vue的初始化
// 需求:vue内部众多模块,而且过程复杂
function Vue (options) {
    if (!(this instanceof Vue)) {// 判断是否new vue
      console.warn('Vue is a constructor and should be called with the `new` keyword');
    }
    this._init(options);
}
  initMixin(Vue);
  stateMixin(Vue);
  eventsMixin(Vue);
  lifecycleMixin(Vue);
  renderMixin(Vue);
export function install (_Vue) {
  if (Vue && _Vue === Vue) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

保障对象只有一个

单例模式

目的:需要确保全局只有一个对象

应用场景:为了避免重复新建,避免多个对象存在互相干扰

// 通过定义一个方法,使用时只允许通过此方法拿到存在内部的同一实例化对象
let Singleton = function(name) {
    this.name = name
}
Singleton.getInstance = function(name) {
    if(this.instance) {
        return this.instance;    
    }
    return this.instance = new Singleton(name);
}

示例(写一个数据存储对象 Store,vue-router)

// 写一个数据存储对象
// 需求:项目中有一个全局的数据储存者,这个储存者智能有一个,不然后会需要进行同步,增加复杂度。
//vue
function Store(){ // 作为构造函数使用的 store ,规范约定应使用Pascal case命名【Store】 ;
  if(Store.install){
    return Store.install;
  }
  this.store={
  }
  Store.install=this;
}
Store.install=null;
var s1 = new Store();
var s2 = new Store();
s1.store.a = 1;
console.log(s2)
// vue-router
// 需求:vue-router必须保障全局有且只有一个,否则的话会错乱。
let _Vue;//vue变量
function install (_Vue) {
  if (install.installed && _Vue === Vue) return
  install.installed = true
  
  _Vue = Vue// 未new过,就付一下值
}
vue.use// 会调用vue.install()

总结

1. 如果你写的模块,需要大量创建类似对象——工厂模式;
2. 需要创建一个需要大量参数,且内部模块庞大——建造者模式;
3. 防止重复注册,防止多个对象互相干扰——单例模式;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值