JavaScript形而上的策略模式

本文介绍了策略模式的概念及其在JavaScript中的实现。策略模式允许在运行时选择算法,通过将算法封装成对象,实现算法之间的互换。文章提供了面向对象及函数式的实现示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是策略模式?

先看代码片段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));

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

转载于:https://www.cnblogs.com/samwu/p/9438699.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值