1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| const betaCalcPre = { currentValue: 0, setValue(newValue) { this.currentValue = newValue; console.log(this.currentValue); }, plus(addend) { this.setValue(this.currentValue + addend); }, minus(subtrahend) { this.setValue(this.currentValue - subtrahend); }, register(plugin) { const {name, exec} = plugin; this[name] = exec; } };
// In many plugin systems, it’s common for plugins to have two parts: // Code to be executed // Metadata (like a name, description, version number, dependencies, etc.) const squaredPluginPre = { name: 'squared', exec: function() { this.setValue(this.currentValue * this.currentValue) } }
betaCalcPre.register(squaredPluginPre); /* 缺点: 1. 插件能访问父类this,违反 the open-closed principle,能直接修改父类的方法,导致出现不可预期行为 2. 插件提供的squared方法产生了副作用,引用不透明 */
betaCalcPre.setValue(3); // => 3 betaCalcPre.plus(2); // => 5 betaCalcPre.squared(); // => 25 betaCalcPre.squared(); // => 625
const betaCalc = { currentValue: 0, setValue(value) { this.currentValue = value; console.log(this.currentValue); }, core: { 'plus': (currentVal, addend) => currentVal + addend, 'minus': (currentVal, subtrahend) => currentVal - subtrahend },
// plugins members can't access betaCalc this plugins: {},
// change to pure functions press(buttonName, newVal) { const func = this.core[buttonName] || this.plugins[buttonName]; this.setValue(func(this.currentValue, newVal)); },
register(plugin) { const { name, exec } = plugin; this.plugins[name] = exec; } }; const squaredPlugin = { name: 'squared', exec: function(currentValue) { return currentValue * currentValue; } };
betaCalc.register(squaredPlugin);
betaCalc.setValue(3); // => 3 betaCalc.press('plus', 2); // => 5 betaCalc.press('squared'); // => 25 betaCalc.press('squared'); // => 625
|