JS设计模式(1)----复习
目录
[TOC]
构造器模式
在面向对象的编程语言中,构造器是一个类中用来初始化新对象的特殊方法。并且可以接受参数用来设定实例对象的属性和方法。
基本构造器
在 JS 中,ES6之前是不支持类这个概念的,所以一般用函数来表示一个构造器,使用方法是在构造器函数前使用 new 关键字。
// 构造函数
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
// 原型属性添加 sayName 方法
Person.prototype.sayName = function () {
return 'hi! I am ' + this.name + '.'
}
// 使用
var person = new Person('zkk', 22, 'male')
console.log(person.sayName()) // => hi! I am zkk.
es6 之后
// 类声明
class Person {
constructor(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
}
sayName() {
return 'hi! I am ' + this.name + '.'
}
}
// 使用
var person = new Person('zkk', 22, 'male')
console.log(person.sayName()) // => hi! I am zkk.
原型(Prototype)模式
**** 是指原型实例指向创建对象的种类,并通过拷贝这些原型创建新的对象,是一种用来创建对象的模式, 也就是创建一个对象作为另一个对象的prototype属性。
原型模式最大的方便就是我们创建对象的时候不一定非得使用类模板,我们完成可以将一个对象来做模板生成新对象。
const engineer = {
name: "工程师",
age: 18,
skills: "",
doWork: function () {
console.log(`${this.name}今年${this.age}岁,使用${this.skills}开发`);
}
}
let webEngineer = Object.create(engineer);
console.log('webEngineer:', webEngineer);
webEngineer.skills = "html,js,css";
webEngineer.name = "爱钱的大傻憨";
webEngineer.doWork();//爱钱的大傻憨今年18岁,使用html,js,css开发
console.log('webEngineer:', webEngineer);
工厂模式
工厂模式 的目的是为了创建对象,它通常在类或者类的静态方法中实现,具有以下目标:
- 当创建相似对象时执行重复操作
- 当编译时不知道具体类型的情况下,为工厂客户提供一个创建对象的接口
工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类。
由一个工厂对象决定,创建某一种产品对象的实例,主要用来创建同一类对象
简单工厂的优点在于你只需要一个正确的参数,就可以获取到你所需要的对象而无需知道创建细节但是在函数内包含了所有对象的创建创建逻辑和判断逻辑代码
工厂模式实现后台权限路由
function UserFactory(role) {
function User(role, page) {
this.role = role
this.page = page
}
switch (role) {
case 'superadmin':
return new User('superadmin', ['home', 'user_mange', 'right_mange', 'news_mange'])
break;
case 'admin':
return new User('admin', ['home', 'user_mange', 'news_mange'])
break;
case 'editor':
return new User('editor', ['home', 'news_mange'])
break;
default:
throw new Error('参数错误')
}
}
let user = UserFactory('admin')
console.log(user);
抽象工厂
这也是针对工厂模式无法应对多对象多复杂对象而出的一种模式,抽象工厂模式并不是直接生成实例,而是对于产品的一个分类的创建
class User {
constructor(name, role, page) {
this.name = name
this.role = role
this.page = page
}
welcome() {
console.log('欢迎回来', this.name);
}
dataShow() {
throw new Error('抽象方法需要被实现')
}
}
class SuperAdmin extends User {
constructor(name) {
super(name, 'superadmin', ['home', 'user_mange', 'right_mange', 'news_mange'])
}
dataShow() {
console.log("superadmin_dataShow");
}
addRight() { }
addUser() { }
}
class Admin extends User {
constructor(name) {
super(name, 'admin', ['home', 'user_mange', 'news_mange'])
}
dataShow() {
console.log("admin_dataShow");
}
addUser() { }
}
class Editor extends User {
constructor(name) {
super(name, 'editor', ['home', 'news_mange'])
}
dataShow() {
console.log("editor_dataShow");
}
}
function getAbstactUserFactory(role) {
switch (role) {
case 'superadmin':
return SuperAdmin
break;
case 'admin':
return Admin
break;
case 'editor':
return Editor
break;
default:
throw new Error('参数错误')
}
}
let userClass = getAbstactUserFactory('superadmin')
let user = new userClass('ZS')
console.log(user);
user.dataShow()
user.welcome()
建造者模式
建造者模式属于创建模式的一种,提供一种创建复杂对象的方式,他将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
建造者模式是一步一步的创建一个复杂对象,它允许用户只通过指定复杂的对象的类型和内容就可以构建它们,用户不需要指定内部的具体构建细节
class NavBar {
init() {
console.log('NavBar init');
}
getData() {
console.log('NavBar getData');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok')
}, 1000);
})
}
render() {
console.log('NavBar render');
}
}
class List {
init() {
console.log('List init');
}
getData() {
console.log('List getData');
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok')
}, 1000);
})
}
render() {
console.log('List render');
}
}
class Creator {
async startBuild(builder) {
await builder.init()
let res = await builder.getData()
console.log(res);
await builder.render()
}
}
const op = new Creator()
op.startBuild(new NavBar())
op.startBuild(new List())
建造者模式将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可以采取不同的表示,工厂模式主要是为了创建对象实例或者类族(抽象工厂),关心的是最终产生(创建)的是什么,而不关心创建过程,而建造者模式关心的是创建这个对象的整个过程甚至创建对象的每个细节
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点,
主要解决一个全局使用类,频繁的创建和销毁,占用内存
var single = (function () {
let instance
function User(name, age) {
this.name = name
this.age = age
}
return function (name, age) {
if (!instance) {
instance = new User(name, age)
}
return instance
}
return instance
})()
let person = single('zs', 18)
let person1 = single('ls', 20)
console.log(person, person1);
class Singleon {
constructor(name, age) {
if (!Singleon.instance) {
this.name = name
this.age = age
Singleon.instance = this
}
return Singleon.instance
}
}
let person3 = new Singleon('zs', 18)
let person4 = new Singleon('ls', 20)
console.log(person3, person4);
装饰器模式
装饰器模式能够很好的对已有的功能进行拓展,这样不会更改原有代码,对其他的业务产生影响,还方便我们在较小的改动下对软件进行扩展
Function.prototype.before = function (beforefn) {
let _this = this
return function () {
// 先执行前置函数调用
beforefn.apply(this, arguments)
// 执行原来的函数
return _this.apply(this, arguments)
}
}
Function.prototype.after = function (afterfn) {
let _this = this
return function () {
let res = _this.apply(this, arguments)
afterfn.apply(this, arguments)
return res
}
}
function test() {
console.log(222);
}
let test1 = test.before(function () {
console.log(111);
}).after(function (params) {
console.log(3333);
})
text1()
function ajax(url, methods, params) {
console.log(url, methods, params);
}
ajax1 = ajax.before((url, methods, params) => {
params.token = '123456'
})
ajax1('/ap1', 'post', {
name: 'zs'
})
适配器模式
将一个类的接口转换成客户希望的另一个接口,适配器让那些接口不兼容的类可以一起工作
class TencetMap {
show() {
console.log('开始渲染腾讯地图');
}
}
class BaiduMap {
display() {
console.log('开始渲染百度地图');
}
}
class TencetAdapater extends TencetMap {
constructor() {
super()
}
display() {
this.show()
}
}
function renderMap(map) {
map.display()
}
renderMap(new TencetAdapater())
renderMap(new BaiduMap())
适配器不去改变实现层,那不属于它的职责范围,它干涉了抽象的过程,外部接口的适配器让同一个方法适用于多种系统
模板方法模式
模板方法模式由两部分组成,第一部分是抽象父类,第二部分是具体实现的子类,通常在抽象父类中封装了子类的算法框架,包括实现一些公共方法以及封装子类中所有方法的执行顺序,子类通过继承这个抽象类,也继承了整个算法结构,并且可以选择重写父类方法
var Container = function (params = {}) {
var F = function () { }
F.prototype.init = async function () {
let list = await this.getData()
this.Render(list)
}
F.prototype.getData = params.getData || function () {
throw new Error('必须传入getData')
}
F.prototype.Render = function (list) {
console.log('Render', list);
}
return F
}
let MyClass = Container({
getData() {
console.log('获取列表数据');
return [1, 2, 3]
}
})
new MyClass().init()
let MyClass2 = Container({
getData() {
console.log('获取新闻数据');
return [4, 5, 6]
}
})
new MyClass2().init()
模板方法模式是一种典型的通过封装变化提高系统扩展性的设计模式,运用了模板方法模式的程序中,子类方法种类和执行顺序都是不变的,但是子类的方法具体实现规则是可变的,父类是个模板,子类可以添加,就增加了不同功能