zoukankan      html  css  js  c++  java
  • 设计模式详解(一)-- 创建型设计模式

    阅读目录

    单例模式

    概念:单例模式确保系统中有唯一的一个对象的实例,如果实例存在,就直接返回创建的实例,不会被重复创建,从全局命名空间里提供一个唯一的访问点(唯一实例)来访问该对象。

    应用场景:页面窗口弹窗

    项目案例:

    var CreateMask = (function () {
        var instance;
        var CreateMask = function (html) {
            if (instance) {
                return instance;
            }
            this.html = html;
            this.init();
            return instance = this;
        };
        CreateMask.prototype.init = function () {
            var div = document.createElement('div');
            div.innerHTML = this.html;
            document.body.appendChild(div);
        };
        return CreateMask;
    })();
    
    var instance1 = new CreateMask('instance1');
    var instance2 = new CreateMask('instance2');
    alert(instance1 === instance2); // true,只创建了instance1实例

    原型模式

    概念: 用原型实例指向创建对象的类,每一个原型实例都能共享原型的属性与方法

    原型对象:只要创建了一个新的函数,就根据一组特定的规则给这个函数创建一个prototype属性,这个属性指向这个函数的原型对象

    JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__的内置属性,用于指向创建它的函数对象的原型对象prototype

    实例也有__proto__属性,指向它的原型对象

    原型对象也有__proto__属性,它指向创建它的函数对象(Object)的prototype

     function Person(){};
     Person.prototype.name = 'prototype';
     Person.prototype.age = 29;
    Person.prototype.job = "software Engineer" Person.prototype.sayName
    = function(){ console.log(this.name); } var person1 = new Person(); var person2 = new Person(); console.log(person1 == person2) //false console.log(person1.__proto__ == person2.__proto__); //true console.log(Person.prototype.constructor == Person); //true console.log(person2.__proto__ == Person.prototype); //true

    原型对象、函数、实例关系图:

    使用hasOwnProperty可以检测属性是在实例中还是原型对象中,使用in操作符只能检测具有这个属性,无法判断是实例还是原型对象

    function Person(){};
     Person.prototype.name = 'prototype';
     Person.prototype.age = 18;
     Person.prototype.getName = function(){
        console.log(this.name);
     }
    
     var person1 = new Person();
     var person2 = new Person();
    
     person1.name = "person1";
     console.log(person1.hasOwnProperty("name")); //true
     delete person1.name;
     console.log(person1.hasOwnProperty("name")); //false
     console.log("name" in person1); //true
     delete person1.name;
     console.log("name" in person1); //false
     console.log("name" in person1.__proto__); //true

    弊端:1、原型模式无法对所有实例的属性进行定制话,所有实例都具有相同的属性值;2、针对引用类型属性,对实例属性赋值不会更改原型对象属性值,而对实例属性使用方法,则会更改原型对象的属性值

    解释:引用时会从当前对象开始一直到原型链的最顶端,直到找到指定的属性。而赋值操作只会对当前实例的属性产生影响,如果没有就新建一个,而不会去原型链上找。

    function Person(){};
     Person.prototype.name = 'prototype';
     Person.prototype.age = 18;
     Person.prototype.fruits = ["apple","banana"]
     Person.prototype.getName = function(){
        console.log(this.name);
     }
    
     var person1 = new Person();
     var person2 = new Person();
    
     person1.fruits = ["apple","banana","melons"];
     console.log(person2.__proto__.fruits); //["apple","banana"]
     console.log(person2.fruits); //["apple","banana"]
    
     person1.fruits.push("melons"); ////前三行注释掉再运行
     console.log(person2.__proto__.fruits);//["apple","banana","melons"]
     console.log(person2.fruits); //["apple","banana","melons"]

    建造者模式

    概念:将一个复杂的对象的构建与它的表示分离,抽象出复杂对象的创建过程,动态创建具有复合属性的对象

    应用场景:造汽车&买汽车,工厂---建造者模式,负责复杂的汽车制造,买汽车者--用户,根据型号直接购买,无需知道汽车怎么组装,适合构造的产品之间差异性不大,组成部分相似的场景

    角色:Director--用于构建一个使用Builder接口的对象和控制汽车生产过程,而客户无需知道汽车生产的细节,只需知道怎么使用即可。

               Builder--声明ConcreateBuilder的公共接口,抽象类,返回产品(汽车)

               ConcreateBuilder--实现Builder接口创建汽车产品(产品有多种,奔驰,东风日产,部件都差不多)

               Product--具体的产品(汽车的每一个部件)

    项目案例:--注:没找到js的案例,以下为java的案例,关注思想即可

    public class Car {  //Product
    
        private IBelt belt; 
        private IMotor motor; 
        
        public IBelt getBelt() { 
            return belt; 
        } 
        public void setBelt(IBelt belt) { 
            this.belt = belt; 
        } 
        public IMotor getMotor() { 
            return motor; 
        } 
        public void setMotor(IMotor motor) { 
            this.motor = motor; 
        } 
    } 
    public abstract class Builder { //抽象builder类
        abstract void buildBelt(); 
        abstract void buildMotor(); 
        abstract Bike createCar(); 
    }
    public class audiBuilder extends Builder{ //// 具体 builder 类 
        private Car iCar = new Car(); 
        @Override 
        void buildBelt() { 
            mBike.setBelt('audi-belt'); 
        } 
        @Override 
        void buildMotor() { 
            iCar.setMotor('audi-motor'); 
        } 
        @Override 
        Car createCar() { 
            return iCar; 
        } 
    } 
    public class chevroletBuilder extends Builder{ //// 具体 builder 类 
        private Car iCar = new Car(); 
        @Override 
        void buildBelt() { 
            mBike.setBelt('chevrolet-belt'); 
        } 
        @Override 
        void buildMotor() { 
            iCar.setMotor('chevrolet-motor'); 
        } 
        @Override 
        Car createCar() { 
            return iCar; 
        } 
    } 
    public class Director { //Director
        private Builder mBuilder = null; 
        public Director(Builder builder) { 
            mBuilder = builder; 
        } 
        public Car construct() { 
            mBuilder.buildBelt(); 
            mBuilder.buildMotor(); 
            return mBuilder.createCar(); 
        } 
    }

    简单工厂模式

    概念:由单个工厂对象对创建某种产品对象的实例有决定权,产品对象是属于同一类型

    应用场景:创建的对象数量较少,对象的创建逻辑较简单

    项目案例:不同用户控制相应权限

    let UserFactory = function (role) {
       function User(operate) {
        this.name = operate.name;
        this.viewPage = operate.viewPages;
      }
    
      switch (role) {
        case 'superAdmin':
          return new User({ name: '超级管理员', viewPage: ['用户权限管理', '日志', '数据展示'] });
          break;
        case 'admin':
          return new User({ name: '管理员', viewPage: ['日志', '数据展示'] });
          break;
        case 'user':
          return new User({ name: '普通用户', viewPage: ['数据展示'] });
          break;
        default:
          throw new Error('参数错误, 可选参数:superAdmin、admin、user')
      }
    }
    
    let superAdmin = UserFactory('superAdmin');
    let admin = UserFactory('admin') 
    let normalUser = UserFactory('user');

    工厂方法模式

    概念:提供一个创建对象的接口,但不实现创建对象的具体类,由子类去实例化具体类

    项目实例:

    let UserFactory = function(role) {
      if(this instanceof UserFactory) {
        var s = new this[role]();
        return s;
      } else {
        return new UserFactory(role);
      }
    }
    UserFactory.prototype = {
      SuperAdmin: function() {
        this.name = "超级管理员",
        this.viewPage = ['用户权限管理', '日志', '数据展示']
      },
      Admin: function() {
        this.name = "管理员",
        this.viewPage = ['日志', '数据展示']
      },
      NormalUser: function() {
        this.name = '普通用户',
        this.viewPage = ['数据展示']
      }
    }
    
    let superAdmin = UserFactory('SuperAdmin');
    let admin = UserFactory('Admin');
    let normalUser = UserFactory('NormalUser');

    以下为第二种写法

    let UserFactory = function() {}
    UserFactory.prototype.userRole = function(name){
        var user;
        switch(name){
            case 'SuperAdmin':user = new SuperAdmin();break;
            case 'Admin':user = new Admin();break;
            case 'NormalUser':user = new NormalUser();break;
         }
         return user;
    }
    
    function SuperAdmin(){
        this.name = "超级管理员";
        this.viewPage = ['用户权限管理', '日志', '数据展示']
    }
    function Admin(){
        this.name = "管理员";
        this.viewPage = ['日志', '数据展示']
    }
    function NormalUser(){
        this.name = "普通用户";
        this.viewPage = ['数据展示']
    }
    
    let superAdmin = new UserFactory();
    superAdmin.userRole("SuperAdmin");
    let admin = new UserFactory('Admin');
    admin.userRole("admin");
    let normalUser = new UserFactory('NormalUser');
    normalUser.userRole("normalUser");

    抽象工厂模式

    概念:抽象工厂不直接生成实例,在父类中定义抽象方法,让子类继承

    项目实例:

    class AbstractFactory { //约束工厂类实现
      getPerson() {
        throw new Error("子类请实现接口");
      }
    
      getAnimal() {
        throw new Error("子类请实现接口");
      }
    }
    class Factory {
      constructor(choice) {
        choice = choice.toLocaleLowerCase();
        switch (choice) {
          case "person":
            return new PersonFactory();
          case "animal":
            return new AnimalFactory();
          default:
            break;
        }
      }
    }
    class PersonFactory extends AbstractFactory {
      getPerson(person) {
        person = person.toLocaleLowerCase();
        switch (person) {
          case "male":
            return new Male();
          case "female":
            return new Female();
          default:
            break;
        }
      }
    
      getAnimal() {
        return null;
      }
    }
    class AnimalFactory extends AbstractFactory {
      getPerson() {
        return null;
      }
    
      getAnimal(animal) {
        animal = animal.toLocaleLowerCase();
        switch (animal) {
          case "cat":
            return new Cat();
          case "dog":
            return new Dog();
          default:
            break;
        }
      }
    }
    
    class Dog {
      run() {
        console.log("dog");
      }
    }
    
    class Cat {
      run() {
        console.log("cat");
      }
    }
    class Male {
      run() {
        console.log("male");
      }
    }
    
    class Female {
      run() {
        console.log("female");
      }
    }
    let personFactory = new Factory("person");
    let male = personFactory.getPerson("male");
    let female = personFactory.getPerson("female");
    male.run();
    female.run();
  • 相关阅读:
    自动补全命令插件的安装(centos)
    vim tab设置为4个空格
    CentOS系统将UTC时间修改为CST时间
    Zabbix报错 zabbix:cannot convert value to numeric type解决
    php-fpm平滑重启开启关闭
    虚拟机启动network服务失败,Job for network.service failed because the control process exited with error code问题
    Tomcat中设置站点子目录的方法
    WordPress添加背景音乐plus教程
    WordPress使用必应每日一图作登录页面背景
    WordPress自定义美化
  • 原文地址:https://www.cnblogs.com/zhangyaolan/p/11141178.html
Copyright © 2011-2022 走看看