前端設計模式

一、工廠模式

工廠模式例子:$() 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

相關文章
相關標籤/搜索