NazimovDmitrii
8/27/2019 - 5:44 PM

[JS ES6 Паттерн ЦЕПОЧКА ОБЯЗАННОСТЕЙ (Chain of responsibility)] #js #ES6 #ООП #Паттерны

[JS ES6 Паттерн ЦЕПОЧКА ОБЯЗАННОСТЕЙ (Chain of responsibility)] #js #ES6 #ООП #Паттерны

/**
 *
 * ПАТТЕРН ЦЕПОЧКА ОБЯЗАННОСТЕЙ (Chain of responsibility)
 *
 * Паттерн ЦЕПОЧКА ОБЯЗАННОСТЕЙ - это поведенческий паттерн проектирования, который позволяет передавать запросы
 * последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам
 * и стоит ли передавать запрос дальше по цепи.
 *
 * Пример: у вас есть три счета (A, B, C) с разными суммами и разным приоритетом использования. Сначала проверяется A,
 * если на нем достаточно денег для покупки, то цепочка прерывается. Иначе проверяется B, затем C. Цепь будет
 * продолжаться, пока не найдет подходящий обработчик.
 *
 */


class Account {

    setNext(account) {
        this.successor = account
    }

    pay(amountToPay) {
        if (this.canPay(amountToPay)) {
            console.log(`Paid ${amountToPay} using ${this.name}`)
        } else if (this.successor) {
            console.log(`Cannot pay using ${this.name}. Proceeding...`)
            this.successor.pay(amountToPay)
        } else {
            console.log('None of the accounts have enough balance')
        }
    }

    canPay(amount) {
        return this.balance >= amount
    }
}

class Bank extends Account {
    constructor(balance) {
        super()
        this.name = 'bank'
        this.balance = balance
    }
}

class Paypal extends Account {
    constructor(balance) {
        super()
        this.name = 'Paypal'
        this.balance = balance
    }
}

class Bitcoin extends Account {
    constructor(balance) {
        super()
        this.name = 'bitcoin'
        this.balance = balance
    }
}


// Сделаем такую цепочку
//      bank->paypal->bitcoin
//
// Приоритет у банка!
// Если банк не может оплатить, переходим к Paypal
// Если Paypal не может, переходим к Bitcoin

const bank = new Bank(100)          // Bank with balance 100
const paypal = new Paypal(200)      // Paypal with balance 200
const bitcoin = new Bitcoin(300)    // Bitcoin with balance 300

bank.setNext(paypal)
paypal.setNext(bitcoin)

// Начнём с банка
bank.pay(259)

// Cannot pay using bank. Proceeding ..
// Cannot pay using paypal. Proceeding ..:
// Paid 259 using Bitcoin!




// Еще один вариант цепочки обязанностей, кумулятивный:
class CumulativeSum {
    constructor(intialValue = 0) {
        this.sum = intialValue;
    }

    add(value) {
        this.sum += value;
        return this;
    }
}

// usage
const sum1 = new CumulativeSum();
console.log(sum1.add(10).add(2).add(50)); // 62


const sum2 = new CumulativeSum(10);
console.log(sum2.add(10).add(20).add(5)); // 45