设计模式详解(一)-- 创建型设计模式

阅读目录

单例模式

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

应用场景:页面窗口弹窗

项目案例:

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();

 

posted @ 2019-07-07 17:50  yaolan  阅读(277)  评论(0编辑  收藏  举报