设计模式详解(一)-- 创建型设计模式
阅读目录
单例模式
概念:单例模式确保系统中有唯一的一个对象的实例,如果实例存在,就直接返回创建的实例,不会被重复创建,从全局命名空间里提供一个唯一的访问点(唯一实例)来访问该对象。
应用场景:页面窗口弹窗
项目案例:
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();