zoukankan      html  css  js  c++  java
  • JavaScript形而上的策略模式

    什么是策略模式?

    先看代码片段1。

    // 代码片段1
    var bonus = new Bonus();
    bonus.setSalary(10000);
    bonus.setStrategy(new performanceS());
    console.log('bounsS' ,bonus.getBonus());
    // => 40000
    
    bonus.setStrategy(new performanceA());
    console.log('bounsA',bonus.getBonus());
    // => 30000
    

    bonus是一个对象,而对象自带上下文。
    这个对象在运行的不同阶段,通过setStrategy设置了不同的参数,导致同样的bonus.getBonus()输出结果不同。
    所以策略模式是指,定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

    下面的代码片段2是代码片段1的定义。

    // 代码片段2
    var performanceS = function () { };
    performanceS.prototype.calculate = function (salary) {
        return salary * 4;
    };
    
    var performanceA = function () { };
    performanceA.prototype.calculate = function (salary) {
        return salary * 3;
    };
    
    var performanceB = function () { };
    performanceB.prototype.calculate = function (salary) {
        return salary * 2;
    };
    
    
    var Bonus = function () {
        this.salary = null;  
        this.strategy = null;
    };
    
    Bonus.prototype.setSalary = function (salary) {
        this.salary = salary; 
    };
    
    Bonus.prototype.setStrategy = function (strategy) {
        this.strategy = strategy;
    };
    
    
    Bonus.prototype.getBonus = function () { 
        return this.strategy.calculate(this.salary); 
    };
    

    改进的策略模式

    同样的bonus.getBonus(),却输出结果不同。
    当业务变得复杂,这会导致代码难以预测。
    我们稍微改进一下,让对象初始化时接收一个策略对象,并且设置策略属性不可修改。

    // 代码片段3
    var bonusFactory = function(strategy){
        this.salary = null;  
        Object.defineProperty(this, 'strategy',{
            value: strategy,
            writable: false,
            configurable:false,
        })
    };
    
    bonusFactory.prototype.setSalary = function (salary) {
        this.salary = salary; 
    };
    
    bonusFactory.prototype.getBonus = function () { 
        return this.strategy.calculate(this.salary); 
    };
    
    var bonusS = new bonusFactory(new performanceS());
    bonusS.setSalary(10000);
    bonusS.strategy = 11;
    console.log('bonusS', bonusS.getBonus());
    
    
    var bonusA = new bonusFactory(new performanceA());
    bonusA.setSalary(10000);
    console.log('bonusA', bonusA.getBonus());
    

    策略模式的函数式写法

    这里使用了名为ramda的函数式工具库。

    var R = require('ramda');
    
    var salaryS = function(salary) {
        return salary * 4;
    };
    
    var salaryA = function(salary) {
        return salary * 3;
    };
    
    var salaryB = function(salary) {
        return salary * 2;
    };
    
    var getBonus = function(salary, strategy){
        return strategy(salary); 
    };
    
    var getBonusFacotry = R.curry(getBonus);
    var getBonusS = getBonusFacotry(R.__, salaryS);
    var getBonusA = getBonusFacotry(R.__, salaryA);
    var getBonusB = getBonusFacotry(R.__, salaryB);
    
    var getBouns1000 = getBonusFacotry(1000, R.__);
    
    console.log('封装奖金计算方式的策略');
    
    console.log(getBonusS(1000));
    console.log(getBonusA(1000));
    console.log(getBonusB(1000));
    
    console.log('封装奖金数目的策略');
    
    console.log(getBouns1000(salaryS));
    console.log(getBouns1000(salaryA));
    console.log(getBouns1000(salaryB));
    

    可以看到函数式写法更加灵活和简洁。

  • 相关阅读:
    Redis数据结构
    PostgreSQL中的onflict
    Lombok注解
    Kafka基本介绍
    Java8特性
    Java8特性Lambda表达式
    网络经济与企业管理(第10章:供应链管理)
    网络经济与企业管理(第9章:企业知识管理)
    网络经济与企业管理(第8章:人力资源管理)
    网络经济与企业管理(第7章:企业财务管理)
  • 原文地址:https://www.cnblogs.com/samwu/p/9438699.html
Copyright © 2011-2022 走看看