NazimovDmitrii
8/20/2019 - 10:02 PM

[JS ES6 Паттерн ЗАМЕСТИТЕЛЬ (proxy)] #js #ES6 #ООП Паттерны#

[JS ES6 Паттерн ЗАМЕСТИТЕЛЬ (proxy)] #js #ES6 #ООП Паттерны#

/**
 *
 * ПАТТЕРН ЗАМЕСТИТЕЛЬ (proxy)
 * Предоставляет суррогатный объект, управляющий доступом к другому объекту.
 * 
 * Заместитель это обертка, которая применяется в следующих случаях:
 * 1. Ленивая инициализация (виртуальный прокси). Когда у вас есть тяжёлый объект,
 * грузящий данные из файловой системы или базы данных.
 * 2. Защита доступа (защищающий прокси). Когда в программе есть разные типы пользователей, и вам хочется
 * защищать объект от неавторизованного доступа. Прокси может проверять доступ при каждом вызове и передавать
 * выполнение служебному объекту, если доступ разрешён.
 * 3. Локальный запуск сервиса (удалённый прокси). Когда настоящий сервисный объект находится на удалённом сервере. Мы пишем код, который получает вызов
метода, каким-то образом передает его по сети и вызывает такой же метод удаленного объекта.
 * В этом случае заместитель транслирует запросы клиента в вызовы по сети в протоколе, понятном удалённому сервису.
 * 4. Логирование запросов (логирующий прокси). Когда требуется хранить историю обращений к сервисному объекту.
 * 5. Кеширование объектов («умная» ссылка). Когда нужно кешировать результаты запросов клиентов и управлять
 * их жизненным циклом.
 */


// ПЕРВЫЙ ВАРИАНТ 
// При такой реализации непонятно в чем отличие от декоратора

class Subject {
    constructor() {
    }

    Request (){
    }
}

class RealSubject extends Subject {
    constructor() {
        super()
        console.log('RealSubject created')
    }

    Request (){
        console.log('RealSubject handles request')
    }
}

class Proxy extends Subject {
    constructor() {
        super()
        console.log('Proxy created')
    }

    Request (){
        this.realSubject = new RealSubject();
        console.log('something another - обертка');
        this.realSubject.Request();
    }
}

function init_Proxy() {
    var proxy = new Proxy()
    proxy.Request()
}
init_Proxy();









// ВТОРОЙ ВАРИАНТ
// Здесь ярко выраженное управление доступом к объекту через proxy (Security)


/*
Door interface :

open()
close()
*/

class LabDoor {
    open() {
        console.log('Opening lab door')
    }

    close() {
        console.log('Closing the lab door')
    }
}
class Security {
    constructor(door) {
        this.door = door
    }

    open(password) {
        if (this.authenticate(password)) {
            this.door.open()
        } else {
            console.log('Big no! It ain\'t possible.')
        }
    }

    authenticate(password) {
        return password === 'ecr@t'
    }

    close() {
        this.door.close()
    }
}
const door = new Security(new LabDoor())
door.open('invalid') // Big no! It ain't possible.

door.open('ecr@t') // Opening lab door
door.close() // Closing lab door









// ТРЕТИЙ ВАРИАНТ
// Здесь задействован синтаксис ES6 + кэширование через proxy
// Target
function networkFetch(url) {
    return `${url} - Response from network`;
}

// Proxy
// ES6 Proxy API = new Proxy(target, handler);
const cache = [];
const proxiedNetworkFetch = new Proxy(networkFetch, {
    apply(target, thisArg, args) {
        const urlParam = args[0];
        if (cache.includes(urlParam)) {
            return `${urlParam} - Response from cache`;
        } else {
            cache.push(urlParam);
            return Reflect.apply(target, thisArg, args);
        }
    },
});

// usage
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from network'
console.log(proxiedNetworkFetch('dogPic.jpg')); // 'dogPic.jpg - Response from cache'