简介
设计模式是我们在解决问题的时候针对特定问题给出的简洁而优化的处理方案
在js设计模式中最核心的思想:封装变化
将变与不变分离,确保变化的部分灵活,不变的部分稳定
1.构造器模式
构造器模式就是构造函数,(用于添加多个对象时,可以简化代码,并且赋值到新的变量中)
使用函数分配到内存从而给到新的变量
对代码进行封装,提高代码的复用性
缺点:
对里面的函数也会每次创建新的内存,(使用原型模式可以解决)
写法
function fun (name, age) {
this.name = name
this.age = age
}
let person = new fun('name', 100)
console.log(person) // fun {name: 'name', age: 100}
2.原型模式
原型模式就是把方法存放放在该对象的原型上,从而减少内存,只存放一次,
使用:
let employeel = {
name: 'name',
age: 100
}
function fun (name, age) {
this.name = name
this.age = age
}
fun.prototype.say = function () {
console.log(this.name, this.age);
}
let person = new fun('name', 100)
person.say() // fun {name: 'name', age: 100}
es6中class类就具有构造器模式和原型模式,也是存放一次,改变内容,
// 使用class类 兼顾构造器模式和原型模式 自动把方法挂在到原型上
class fun1 {
constructor(name, age) {
this.name = name
this.age = age
}
}
let new1 = new fun1('name', 100)
console.log(new1); // fun1 {name: 'name', age: 100}
3.工厂模式
是一种创建对象的设计模式,他通过使用工厂来实现对象的创建,而不是直接使用构造函数,可以减少重复的代码,提高代码的可维护性和扩展性
function User (name, age) {
this.name = name;
this.age = age;
}
// 封装工厂
function UserFactory (role) {
switch (role) {
case 'user': return new User('用户', 15); break;
case 'guest': return new User('游客', 18); break;
case 'admin': return new User('管理员', 20); break;
default: return new User('未知', 0); break;
}
}
let suer = UserFactory('user')
console.log(suer);
class 方式
class Admin { constructor(name, age) { this.name = name; this.age = age; } }
// es6的方式
class UserFactorys {
// 静态方法
static create (role) {
switch (role) {
case 'user': return new Admin('用户', 15); break;
case 'guest': return new Admin('游客', 18); break;
case 'admin': return new Admin('管理员', 20); break;
default: return new Admin('未知', 0); break;
}
}
}
let admin = UserFactorys.create('admin')
console.log(admin);
4.抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是 围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
抽象工厂模式并不直接生成实例,而是用于对产品类簇的创建。
我们先创建一个 User 类(超级工厂),里面有两个方法,welcome() 方法用于欢迎某一类人,dataShow() 方法用于打印某一类人(子类重写的方式)。
之后我们创建三个子类 SuperAdmin、Admin、Editor(其他工厂),均继承自 User,它们继承父类的 name 和 welcome() 方法,重写父类的 dataShow() 方法。
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
welcome () {
console.log(`欢迎${this.name},您的角色是${this.role}`)
}
dataShow () {
throw new Error('抽象方法不能被调用')
}
}
class Admin extends User {
constructor(name) {
super(name, '管理员')
}
dataShow () { console.log('管理员数据展示') }
}
let admin = new Admin('admin')
admin.welcome()
5.建造者模式
建造者模式可以将一个复杂的对象的构建与其表示相分离,使得同样的构建过程可以创建不同的表示
使用
class Navbar {
init () {
console.log('创建导航栏=num');
}
getData () {
console.log('获取导航栏数据=num');
return new Promise((resolve, reject) => {
setTimeout
(() => {
console.log('111');
resolve('导航栏数据')
})
})
}
rander () {
console.log('渲染导航栏=num');
}
}
// 建造者
class Creator {
async starBuild (builter) {
await builter.init()
await builter.getData()
await builter.rander();
}
}
const op = new Creator().starBuild(new Navbar())
6.单例模式
单列模式就是:保证一个类仅有一个实例,并有一个访问他的全局访问点
// 单例模式:保证一个类只有一个实例,并提供一个访问它的全局访问点
// 1.使用闭包实现单例模式
let Singleaton = (function () {
let instance = null
function USer (name, age) {
this.name = name
this.age = age
}
return function
(name, age) {
if (!instance) {
instance = new USer(name, age)
}
return instance
}
})()
let user = Singleaton('张三', 18) // 实例化一次
console.log(user) // 张三;
// es6实现单例模式
class Esingleaton {
constructor(name, age) {
if (!Esingleaton.instance) {
this.name = name
this.age = age
Esingleaton.instance = this
}
return Esingleaton.instance
}
}
let es = new Esingleaton('李四', 20) // 实例化一次
let es6 = new Esingleaton('李四1', 200) // 实例化一次
console.log(es === es6) // true;
7.装饰器模式
是一种结构设计模式,用于在不变原有对象的基础上,动态的给对象添加功能或职责
// 装饰器模式:在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责(方法或属性)
Function.prototype.before = function (beforefn) {
let _this = this
return function () {
// 执行前置的函数调用
beforefn.apply(this, arguments)
// 执行原来的函数
return _this.apply(this, arguments)
}
}
Function.prototype.after = function (after) {
let _this = this
return function () {
let result = _this.apply(this, arguments)
// 执行前置的函数调用
after.apply(this, arguments)
// 执行原来的函数
return result
}
}
function test () {
console.log('111111111111');
return 1
}
// test()
let text1 = test.before(function () {
console.log('222222222222');
}).after(function () {
console.log('333333333333');
})
text1()
8.适配器模式
适配器模式是一种结构型设计模式,用于将一个类的接口转换成客户端所期望的另一个接口,从而使原来不兼容的类可以协同工作,适配器的主要工作是将一个了类的接口转换成客户端所期望的接口,以便客户端可以使用这个类
class TentcentMap {
constructor() {
this.show = () => {
console.log('腾讯地图')
}
}
}
class BaiduMap {
display () {
console.log('百度地图')
}
}
// 适配器模式
class TencentAdaater extends TentcentMap {
constructor(map) {
super()
}
display (map) {
this.show()
}
}
function renderMap (map) {
map.display();
}
renderMap(new TencentAdaater());
renderMap(new BaiduMap());
9.策略模式
定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换
let cal = {
'+': (a, b) => a + b,
'-': (a, b) => a - b,
'*': (a, b) => a * b,
'/': (a, b) => a / b,
}
function calButton (num1, num2, operator) {
if (!cal[operator]) {
return '运算符错误'
}
return cal[operator](num1, num2)
}
console.log(calButton(1, 2, '+'))
10.代理模式
JS代理模式是一种结构性设计模式,它允许你在访问对象之前或之后添加额外的逻辑或控制。JS代理模式是面向对象编程范式中的一个关键概念
// 代理模式
class Star {
paly () {
console.log('唱歌');
}
}
class StarProxy {
constructor() {
this.star = new Star()
}
talk (price) {
if (price > 100000) {
this.star.paly()
} else {
console.log('太贵了')
}
}
}
let jr = new StarProxy()
jr.talk(1000000)
jr.talk(10000)
// es6
let star = {
name: "timo",
workPice: 10000
}
let proxy = new Proxy(star, {
get (sarget, key) {
console.log('访问了');
if (key === 'workPice') {
console.log('访问了');
}
return sarget[key]
},
set (staget, key, value) {
if (key === 'workPice') {
console.log('设置了');
if (value > 10000) {
console.log('可以合作');
} else {
console.log('太贵了');
}
}
}
})