复习设计模式第一天

157 阅读5分钟

这是我参与更文挑战的第18天,活动详情查看:更文挑战

设计模式的简介

设计模式就是一套编目分明,广为人知,可复用的代码经验的总结

工具库:它是一些方法的集合体,比如jquery, underscore,它们里面的方法通常是没有联系的

框架: 一套半成品代码, 它里面也支持一些方法,这些方法之间通常是有联系的

架构: 它是一套大型项目的设计思路

分类

所有的设计模式基本上可以分为三类创建型设计模式,结构型设计模式,行为型设计模式

作用

创建型设计模式的作用: 解决了创建对象时候的问题

结构型设计模式的作用: 解决了对象和类组合在一起时候的问题

行为型设计模式的作用:解决了对象和类偶合,职责之间的关系

历史

设计模式最初是由外国的一个叫做GOF (Gang of Four), 设计模式一共有23种, 设计模式发展至今,已经远远超过23种。

简单工厂模式

举例:

function person(name, age, sex, job) {
	var person = {
		name: name,
		age: age,
		sex: sex,
		job: job
	}
	return person;
}

此时,person就是一个“简单工厂”, 每次放入不同的“原料”, 就可以得到不同的"产品"

执行代码:

var p = person("老王", 40, "男", "厨师");
var p1 = person("老张", 41, "男", "IT");

输出结果:

图片1.png

寄生增强工厂

举例:

// 定义新的工厂
function StrongPerson(name, age, sex) {
	// 这是一个工厂
	// 初始化People
	var p = new People(name, age, sex);
// 对象p添加属性和方法
	p.title = "nihao";
	p.sayNihao = function() {
		console.log("你好");
	}
	return p;
}

执行代码:

// 创建对象
var people = new StrongPerson("小刚", 12, "男");
people.sayHello();
people.sayNihao();

输出结果:

图片2.png

工厂方法

定义: 管理多个类,可以返回多个产品

// 工厂方法: 定义一个工厂, 内部包含多个实例的创建

// 定义构造函数
function Dog() {
	this.type = "dog";
}

// 定义构造函数
function Cat() {
	this.type = "cat";
}

// 定义构造函数
function Pig() {
	this.type = "pig";
}

// 定义新的工厂
function FactoryMethod(type) {
	if (type === "dog") {
		return new Dog();
	} else if (type === "cat") {
		return new Cat();
	} else if (type === "pig") {
		return new Pig();
	}
}

var dog = FactoryMethod("dog");
var cat = FactoryMethod("cat");
var pig = FactoryMethod("pig");

原型与继承

原型:

// 原型, 是构造函数的一个属性,值是一个对象

// 定义构造函数
function People(name, age, sex) {
	this.name = name;
	this.age = age;
	this.sex = sex;
}

// 方法要写在原型上
People.prototype.sayHello = function() {
	console.log("大家好, 我的名字叫做" + this.name + ",我的年龄是" + this.age + ",我是一个" + this.sex + "孩子");
}

继承:

// 定义父类
function People(name, age, sex) {
	this.name = name;
	this.age = age;
	this.sex = sex;
}
// 父类的方法
People.prototype.sayHello = function() {
	console.log("大家好, 我的名字叫做" + this.name + ",我的年龄是" + this.age + ",我是一个" + this.sex + "孩子");
}

// 定义子类
function Student(name, age, sex, grade) {
	// 构造函数式继承
	People.apply(this,  arguments);
	// 子类独有属性
	this.grade = grade;
}

// 继承
// 使用类式继承
// Student.prototype = new People();
// 这种继承方式会丢失子类的原型对象
// 另外,这种继承方式会在子类的原型上多出几个无用的属性

// 我们可以使用ES5提供的Object.create方法
Student.prototype = Object.create(People.prototype);
// 补回
Student.prototype.constructor = Student;

// 子类的方法
Student.prototype.intro = function() {
	console.log("大家好, 我的名字叫做" + this.name + ",我的年龄是" + this.age + ",我是一个" + this.sex + "孩子" + "我今年上" + this.grade + "年级了");
}

执行代码:

// 初始化Student
var s = new Student("小明", 12, "男", 6);
// 调用父类的方法
s.sayHello();
// 调用子类自己的方法
s.intro();

// 检测student是否是Student的实例
console.log(s instanceof Student)
// 检测student是否是People的实例
console.log(s instanceof People);

输出结果:

图片3.png

安全工厂

举例:

// 改造
function People(name, age, sex) {
	// 判断this指向谁, 从而决定代码如何执行
	if (this instanceof People) {
		// 说明使用new来调用, 那么一起照常执行
		this.name = name;
		this.age = age;
		this.sex = sex;
	} else {
		// 说明没有是用new 来调用, 也就是说当做普通函数来调用了, 如果普通函数想要返回一些内容要人为的return
		return new People(name, age, sex);
	}
}


// 测试
// 使用new 来调用构造函数
var p = new People("小明", 12, "男");
console.log(p);


// 不使用new 执行函数
var p1 = People("小强", 11, "男");
console.log(p1);

结果:

图片4.png

闭包类

简单来说就是将类放入闭包中

举例:

// 一个闭包
(function() {})();

// 一个类
function People() {

}

// 闭包类
(function() {
	function People() {

	}
})();

// 如果将类放在全局中, 别人也可以访问到, 想怎么初始化就怎么初始化
// 如果在类放在闭包中,别人就无法操作了。

单例模式

举例:

var single = (function() {
	function People(name, age, sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
	} 
	// 此时确实将People类放入闭包中, 别人也就无法来操作People了
	// 但是,我们自己也无法操作
	// 我们要向外暴露一个接口,让外部可以访问内部的People类
// 定义变量 用来保存单例
	var instance = null;
	// 返回接口函数
	return function(name, age, sex) {
		// 判断单例是否存在
		if (!instance) {
			return instance = new People(name, age, sex);
		}
		// 如果单例已经存在, 直接返回
		return instance;
	}
})();

// 外面无论如何调用, 只能返回一个实例化对象
var p = single("小明", 12, "男");
var p1 = single("小红", 11, "女");

结果:

图片5.png

普通单例

举例:

// 普通单例: 在定义的时候就执行的单例
var single = (function() {
	// 定义类
	function People(name, age, sex) {
		console.log("普通单例");
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	// 定义变量保存单例
	var instance = new People("小明", 12, "男");

	// 定义接口
	return function() {
		// 因为已经实例化过了, 所以就不需要再次判断了
		return instance;
	}
})()

惰性单例

举例:

var single = (function() {
	// 定义类
	function People(name, age, sex) {
		console.log("惰性单例");
		this.name = name;
		this.age = age;
	this.sex = sex;
	}

	// 定义变量保存单例
	var instance = null;

	// 定义接口函数
	return function(name, age, sex) {
		// 判断单例是否存在
		if (!instance) {
			return instance = new People(name, age, sex);
		}
		// 如果单例存在, 直接返回
		return instance;
		}
})();