一、工厂模式
工厂模式例子:$() React.createElement()
class Product {
constructor(name) {
this.name = name
}
init() {
alert('init')
}
func1() {
console.log('func1')
}
func2() {
console.log('func2')
}
}
/**
* 工厂
*/
class Creater {
create(name) {
return new Product(name)
}
}
const creater = new Creater();
const p1 = creater.create('p1');
二、单例模式
单利模式有:$ 登录框 购物车 vuex和redux中的store
class SingleObject {
constructor(){
console.log('this',this)
}
login() {
console.log('login...')
}
}
// 单例模式,实例只是实例一次
// 且只能内部去实例(当然因为js原因,外部去 new SingleObject()也不会报错)
SingleObject.getInstance = (() => {
let instance;
return function () {
if (!instance) {
instance = new SingleObject();
}
return instance;
}
})()
const obj1 = SingleObject.getInstance();
obj1.login();
const obj2 = SingleObject.getInstance();
obj2.login();
// console.log(obj1 === obj2); // true
登录弹出框实现方式
class LoginForm {
constructor() {
this.state = 'hide'
}
show() {
if (this.state === 'show') {
alert('已经是show了');
return;
}
this.state = 'show'
console.log('====>show')
}
hide() {
if (this.state === 'hide') {
alert('已经是hide了');
return;
}
this.state = 'hide'
console.log('====>hide')
}
}
LoginForm.getInstance = (() => {
let form;
return function () {
if (!form) {
form = new LoginForm()
}
return form
}
})();
const page1login = LoginForm.getInstance();
page1login.show();
const page2login = LoginForm.getInstance();
page1login.hide();
三、适配器模式
使用场景:封装旧接口 vue中的computed
class Adaptee {
specificRequest() {
return '德国标准插头'
}
}
class Target {
constructor() {
this.adaptee = new Adaptee()
}
request(){
let info = this.adaptee.specificRequest();
return `${info} - 转换器 - 中国标准插头`
}
}
let target = new Target();
console.log(target.request())
四、装饰器模式
装饰器模式:添加新功能 装饰一下,不改变原来的功能,只是扩展
1、手动实现装饰器
class Circle {
draw() {
console.log('画一个圆形')
}
}
class Decorator {
constructor(circle) {
this.circle = circle;
}
draw() {
this.circle.draw()
}
setRedBorder() {
console.log('设置红色边框')
}
}
const circle = new Circle();
circle.draw();
const dec = new Decorator(circle);
dec.draw()
dec.setRedBorder()
2、ES6装饰器
@testDec
class Demo {
}
function testDec(target) {
target.isDec = '黑黑';
}
console.log(Demo)
alert(Demo.isDec)
// 装饰类加参数
@testDec(true)
class Demo {
}
function testDec(isDec) {
return function (target) {
target.isDec = isDec;
}
}
console.log(Demo)
alert(Demo.isDec)
3、实现log装饰器
class Math {
constructor(a, b) {
this.a = a;
this.b = b;
}
@log
add() {
return this.a + this.b
}
}
function log(target, name, descripter) {
const oldValue = descripter.value;
descripter.value = function () {
console.log(`calling ${name} with `,arguments)
return oldValue.apply(this, arguments); // 因为oldValue不是在target里定义的,所以需要指定this
}
return descripter;
}
const math = new Math(1,2);
console.log(math.add())
4、mixin
function mixin(...list) {
return function (target) {
Object.assign(target.prototype, ...list)
}
}
const Foo = {
foo() {
alert('fool')
}
}
@mixin(Foo)
class MyClass {
}
const my = new MyClass();
my.foo()
5、readonly
// 装饰方法
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
@readonly
detail() {
return `NAME: ${this.name}\n AGE: ${this.age}`
}
}
/**
* 装饰方法
* @param {*} target 默认
* @param {*} name 默认
* @param {*} descripter
*/
function readonly(target, name, descripter) {
console.log(target,name,descripter)
descripter.writable = false;
return descripter //可以注掉
}
const persion = new Person('lihaixing', 31);
console.log(persion.detail())
// 以下会报错
persion.detail = function () {
console.log(111)
}
6、装饰器插件
import { readonly, deprecate } from 'core-decorators';
class Person {
constructor() {
this.name = 'zhangsan'
}
@readonly
sayName() {
return this.name
}
@deprecate('即将费用')
say() {
console.log(this.name)
}
}
const person = new Person();
// person.sayName = function () {}
person.say()
五、代理模式
- 网页事件代理
- Jquery中 $.proxy
- ES6中 Proxy
1 手动实现代理
class RealImg {
constructor(fileName) {
this.fileName = fileName;
this.loadFromDisk()
}
display(){
console.log(`display ${this.fileName}`)
}
loadFromDisk(){
console.log(`loading ${this.fileName} from disk`)
}
}
class ProxyImg {
constructor(fileName){
this.realImg = new RealImg(fileName);
}
display(){
this.realImg.display()
}
}
const proxyImg = new ProxyImg('xxx.png')
proxyImg.display()
2、ES6代理
let star = {
name: 'zhang xxx',
age: 25,
phone: 'star: 13453452359'
}
let agent = new Proxy(star, {
get: function (target, key) {
if (key === 'phone') {
// 返回经纪人电话
return 'agent: 158588585885'
}
if (key === 'price') {
// 明星不报价,经纪人报价
return 120000
}
return target[key]
},
set: function (target, key, value) {
if (key === 'customPrice') {
if (value < 100000) {
throw new Error('价格太低')
} else {
target[key] = value
return true
}
}
}
})
// test
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
agent.customPrice=110000
console.log('agent.customPrice: ',agent.customPrice)
3、jquery代理
import $ from 'jquery'
$('.myText').click(function () {
setTimeout(function () {
$(this).css('background-color', 'red')
})
})
$('.myText').click(function () {
const fn = function () {
$(this).css('background-color', 'red')
}
setTimeout($.proxy(fn, this))
})
六、观察者模式
观察者模式和发布订阅模式区别:
- 订阅发布模式需要三种角色,发布者、事件中心和订阅者。
- 观察者模式需要两种角色,目标和观察者,无事件中心负责通信。
发布订阅场景
- jquery网页事件绑定
- promise
- jquery callbacks
- nodejs自定义事件
class Subject {
constructor() {
this.state = 0;
this.observers = [];
}
getState() {
return this.state
}
setState(state) {
this.state = state;
this.notifyAllObservers()
}
notifyAllObservers() {
this.observers.forEach((observer) => {
observer.update()
})
}
attach(observer) {
this.observers.push(observer)
}
}
class Observer {
constructor(name, subject) {
this.name = name;
this.subject = subject;
// 初始化一个观察者,就要把观察者加到观察者列表中
this.subject.attach(this);
}
update() {
console.log(`${this.name} updated, state: ${this.subject.getState()}`)
}
}
const s = new Subject();
const observer1 = new Observer('gcz1', s);
const observer2 = new Observer('gcz2', s);
const observer3 = new Observer('gcz3', s);
s.setState(1);
s.setState(2);
七、迭代器模式
1、手写迭代器模式
class Container {
constructor(list) {
this.list = list
}
getIterator() {
return new Iterator(this)
}
}
class Iterator {
constructor(container) {
this.list = container.list;
this.index = 0;
}
hasNext() {
return this.index < this.list.length
}
next() {
if (this.hasNext()) {
return this.list[this.index++]
}
return null
}
}
const container = new Container([1, 2, 3, 4, 5]);
window.it1 = container.getIterator();
window.it2 = container.getIterator();
2、es6迭代器
/**
* 场景
* 1. 有序集合:Array Map Set String TypedArray arguments NodeList
* 2. Object 不是有序集合 需要用Map代替
* 3. 一个迭代器可以遍历各种有序数据
* 4. for of 就是迭代器
*/
// Array.prototype[Symbol.iterator] 是一个迭代器函数
const arr = [1, 2, 3, 4];
const iter = arr[Symbol.iterator]();
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
// 也返回迭代器
const iter2 = arr.values()
console.log(iter2.next())
console.log(iter2.next())
八、状态模式
同一个上下文,切换不同的state
class State {
constructor(color) {
this.color = color;
}
handle(context) {
context.setState(this)
}
}
class Context {
constructor() {
this.state = null
}
getState() {
return this.state;
}
setState(state) {
this.state = state;
}
}
/**
* 状态模式
* state不变,只是一直在改变上下文context中的state
* 场景:不同的页面,相似的数据
*/
const context = new Context();
const red = new State('red');
red.handle(context);
const green = new State('green');
green.handle(context);
console.log(context.getState())
九、其它模式还有
桥接模式、中介着模式、备忘录模式、原型模式等
github
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。