图解设计模模式

对于未来的前端都要像全栈过度,那么就可能要操作后台,了解设计模式还是有用的。其实就是一种思想。

工厂模式

工厂模式思想就是类似工厂机器可以造同样功能属性的产品。所以我们只需要创建一个工厂,并且告诉他我们要什么样的产品。


function Horse (name,sex) {
        let obj = new Object()
        //抽象出一个马,这个马具有所有马的特性
        obj.name = name
        obj.sex = sex
        obj.saySex = function () {
            alert(`我的性别是${this.sex}`)
        }
        //定义要生产一类马的属性
        return obj //制造好以后生产
    }
    let banma = Horse('小花','母')
    banma.saySex()             //我的性别是母
创建一个生产猴子的工厂,马都具有相同属性,但是名字却可以不一样,这就是多态性,所以传递参数来命名。
在工作中比如我们有一项相功能,在很多地方都使用了,那么就可以用工厂模式来完成,而不必每次都重新写一次。
比如:我们做一个数字和字母的验证方法。
function Validation (type) {
        let obj = new Object()
        obj.method = function (type) {
            return   //效验规则的结果
        }
        return obj //制造好以后生产
    }
    let reusult = Validation(123)
             //根据reusult结果判断
复制代码

构造器模式

构造器模式的思想和工厂模式其实是一样的,个人认为只是写法不同。

function Horse (name,sex) {
       this.name=name;
       this.sex=sex;
    }
    let banma = new Horse('小花','母');
    //工厂函数使用了new 操作符
    //下图是new做了些什么的图
复制代码

安全模式的构造函数

其实安全构造函数就是为了避免大家不知道你是构造函数,而直接去使用。所以加个判断就好了,如果不是函数。

function Person(content){
  if (this instanceof Person){
  // 判断是不是Person的实例
    this.name = name;
    this.age = age;
    this.sex = sex;
  }else{
    return new Person( content);
  }
}
let banma = new Person('小花');
function Person(type,content){
  if (this instanceof Person){
  // 判断是不是Person的实例
   let  newPerson = this[type](content)
   //添加属性并传递参数。返回新对象
    return newPerson
  }else{
    return new Person(type, content);
  }
}
let banma = new Person('name','小花');

复制代码

建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。建造者模式就像拿一个个对象当砖块,一个个垒起来。工厂模式我们是不需要了解创建结果的过程,而建造者可以清晰的知道建造过程。 应用实例:

es5
//创建一个人类
    var Human = function(param){
        //skill技能
        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;
        //构造器函数:解析姓与名(new构造实例时即刻执行此闭包函数)
        (function(name,that){
          //闭包函数this指向window
            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 'teacher':
                    that.work = '教师';
                    that.workDescript = '分享也是一种快乐';
                break;
                default:
                    that.work = work;
                    that.workDescript = '没有合适的描述';
            }
        })(work,that);
    }
    //添加更换职位的方法
    Work.prototype.changeWork = function(work){
        this.work = work;
    }
    //添加对职位的描述方法
    Work.prototype.changeDescript = function(setence){
        this.workDescript = setence;
    }
    //创建一个应聘者builder
    var Person = function(name,work,param){
        //实例化人对象 创建实例化缓存对象
        var _person = new Human(param);
        //实例化人的姓名
        _person.name = new Named(name);
        //实例化人的期望职位
        _person.work = new Work(work);
        //最后将构建的复杂对象应聘者返回出去
        return _person;
    }
    //测试用例
    var person = new Person('小 明','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); //我每天都在快乐的编程学习  
    console.log(person instanceof Person); //false
    console.log(person instanceof Human); //true
    console.log(person instanceof Named); //false
    
es6 
//父类
class BaseBuilder {
  init() {
    Object.keys(this).forEach(key => {
      const withName = `with${key.substring(0, 1).toUpperCase()}${key.substring(1)}`;
      this[withName] = value => {
        this[key] = value;
        return this;
      }
    })
  }

  build() {
    const keysNoWithers = Object.keys(this).filter(key => typeof this[key] !== 'function');

    return keysNoWithers.reduce((returnValue, key) => {
      return {
        ...returnValue,
        [key]: this[key]
      }
    }, {})
  }
}

//子类1: 书籍建造者类//建造者
class BookBuilder extends BaseBuilder {
  constructor() {
    super();

    this.name = '';
    this.author = '';
    this.price = 0;
    this.category = '';
    
    super.init();
  }
}

//子类2: 印刷厂建造者类 //建造者
class printHouseBuilder extends BaseBuilder {
  constructor() {
    super();

    this.name = '';
    this.location = '';
    this.quality = '';

    super.init();
  }
}

//调用书籍建造者类
const book = new BookBuilder()
  .withName("高效能人士的七个习惯")
  .withAuthor('史蒂芬·柯维')
  .withPrice(51)
  .withCategory('励志')
  .build();
//每次执行一个方法就是一次建造

//调用印刷厂建造类
const printHouse = new printHouseBuilder()
  .withName('新华印刷厂')
  .withLocation('北京海淀区')
  .withQuality('A')
  .build(); //建造过程
复制代码

优点: 1、建造者独立,易扩展。 2、便于控制细节风险。 缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。 使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。 注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。其实就是复合型工厂模式。

单例模式惰性加载

function createXHR(){ 
     if (typeof XMLHttpRequest != "undefined"){ 
     createXHR = function(){ 
     return new XMLHttpRequest(); 
     }; 
 } else if (typeof ActiveXObject != "undefined"){ 
     createXHR = function(){ 
     if (typeof arguments.callee.activeXString != "string"){ 
         var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", 
         "MSXML2.XMLHttp"], 
         i, len; 
         for (i=0,len=versions.length; i < len; i++){ 
             try { 
                 new ActiveXObject(versions[i]); 
                 arguments.callee.activeXString = versions[i]; 
                 break; 
             } catch (ex){ 
             //skip 
             } 
         } 
     } 
     return new ActiveXObject(arguments.callee.activeXString); 
     }; 
 } else { 
 createXHR = function(){ 
 throw new Error("No XHR object available."); 
        }; 
    } 
 return createXHR(); 
} 
这是第一段检测代码浏览器支持内置 XHR是否支持。单例模式的思想可以为我们提高代码效率减少不必要的重复步骤。
在这个惰性载入的 createXHR()中,if 语句的每一个分支都会为 createXHR 变量赋值,有效覆
盖了原有的函数。最后一步便是调用新赋的函数。下一次调用 createXHR()的时候,就会直接调用被
分配的函数,这样就不用再次执行 if 语句了。

复制代码

期待一拳赶快更新。后半部分下次写吧,写累了。 参考:js高级编程,js设计模式。

转载于:https://juejin.im/post/5cf9d755e51d45108c59a513

猜你喜欢

转载自blog.csdn.net/weixin_34195364/article/details/91423477