一、构造器
模式
需求:录入员工信息。
原始方法:
const employee1 = {
name: "张三",
age: 18
}
const employee2 = {
name: "李四",
age: 20
}
按以上方法,如员工如要录入多个信息或多个员工就会显得十分臃肿复杂,这时我们可以用到构造器模式:
function Employee(name, age) {
this.name = name
this.age = age
}
const e1 = new Employee("张三", 18)
const e2 = new Employee("李四", 20)
二、原型
模式
按照以上方法,如想在构造函数Employee上加上一个say方法,则
function Employee(name, age) {
this.name = name
this.age = age
this.say = function() {
console.log("我的名字叫" + name + ",我今年" + age + "岁。")
}
}
但是,这样添加会有一个问题,每次在new一个Employee实例的时候都要重新开辟一个空间去存储say方法,会占用大量空间,不符合代码的可复用性,此时我们可以用到原型模式:
function Employee(name, age) {
this.name = name
this.age = age
}
Employee.prototype.say = function() {
console.log("我的名字叫" + this.name + ",我今年" + this.age + "岁。")
}
我们可以把代码提升一下,使用ES6中的class来构造函数:
class Employee {
constructor(name, age) {
this.name = name
this.age = age
}
say() {
console.log("我的名字叫" + this.name + ",我今年" + this.age + "岁。")
}
}
以上代码中,我们可以发现,class这种写法是兼顾构造器模式和原型模式的,constructor中放构造器所写的变量,在Employee中写原型上的变量和方法。
三、工厂
模式
由一个工厂对象决定创建某一产品对象类的实例,主要用来创建同一类对象。
如在后台管理系统中我们需要根据登录的用户信息去获取该用户对应的权限:
class User {
constructor(role, permission) {
this.role = role
this.permission = permission
}
static Userfactory(role) {
switch (role) {
case "superadmin":
return new User("superadmin", ["home", "user-manage", "goods-manage", "news-manage"])
break
case "admin":
return new User("admin", ["home", "goods-manage", "news-manage"])
break
case "aditor":
return new User("aditor", ["home"])
break
default:
throw new Error("参数错误!")
}
}
}
console.log(User.Userfactory("aditor"));
缺点:当我们需要创建更多类型的对象时,工厂函数就会成为一个超级庞大的函数,难以维护,所以工厂函数只适用于创建的对象数量少、对象的创建逻辑不复杂时使用。
四、抽象工厂
模式
抽象工厂模式并不直接生成实例,而是用于对产品类的创建。
class User {
constructor(name, role, permission) {
this.name = name
this.role = role
this.permission = permission
}
welcome() {
console.log("欢迎回来," + this.name);
}
showData() {
throw new Error("抽象方法需要被实现")
}
}
class SuperAdmin extends User {
constructor(name) {
super(name, "superadmin", ["home", "user-manage", "goods-manage", "news-manage"])
}
showData() {
console.log("superadmin-show-data");
}
addUser() { }
}
class Admin extends User {
constructor(name) {
super(name, "admin", ["home", "goods-manage", "news-manage"])
}
showData() {
console.log("admin-show-data");
}
}
class Aditor extends User {
constructor(name) {
super(name, "aditor", ["home"])
}
showData() {
console.log("aditor-show-data");
}
}
function getAbstactUserFactory(role) {
switch (role) {
case "superadmin":
return SuperAdmin
case "admin":
return Admin
case "aditor":
return Aditor
}
}
const UserClass = getAbstactUserFactory("admin")
const user = new UserClass("张三")
console.log(user.welcome()); // 欢迎回来,张三
区别:工厂模式返回的是具体的对象
,而抽象工厂模式返回的是具体的类
。
五、建造者
模式
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
举例:例如网页上获取导航栏以及导航栏所对应的数据列表。
class Navbar {
init() { console.log("navbar-init") }
getData() {
return new Promise(resolve => {
setTimeout(() => {
resolve()
console.log("navbar-getdata")
})
}, 1000)
}
render() { console.log("navbar-render") }
}
class List{
init() { console.log("list-init") }
getData() {
return new Promise(resolve => {
setTimeout(() => {
resolve()
console.log("list-getdata")
})
}, 1000)
}
render() { console.log("list-render") }
}
class Creator {
async startBuild(builder) {
await builder.init()
await builder.getData()
await builder.render()
}
}
const op = new Creator()
op.startBuild(new NavBar())
op.startBuild(new List())
建造者模式关心的是创建这个对象的整个过程,甚至创建对象的每一个细节。
六、单例
模式
定义:保证一个类仅有一个
实例,并提供一个访问它的全局访问点。主要解决一个全局使用的类频繁地创建
和销毁
,占用内存(例如vue中的store
)。
(1)ES5的写法(闭包)
const Singleton = (function() {
let instance
function User(name, age) {
this.name = name
this.age = age
}
return function(name, age) {
if (!instanace) {
instance = new User(name, age)
}
return instance
}
})()
(2)ES6的写法
class Singleton = {
constructor(name, age) {
if (!Singleton.instance) {
this.name = name
this.age = age
Singleton.instance = this
}
return Singleton.instance
}
}