前端设计模式

一、工厂模式

工厂模式例子:$() React.createElement()css

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中的storevue

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

登陆弹出框实现方式jquery

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();

3、适配器模式

使用场景:封装旧接口 vue中的computedvuex

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())

4、装饰器模式

装饰器模式:添加新功能 装饰一下,不改变原来的功能,只是扩展redux

一、手动实现装饰器

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()

二、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)

三、实现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())

四、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()

五、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)
}

六、装饰器插件

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()

5、代理模式

    1. 网页事件代理
    1. Jquery中 $.proxy
    1. 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()

二、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)

三、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))
})

未完持续...app

相关文章
相关标签/搜索