JavaScript中Command模式与Strategy模式的区别及理解验证
答:你的理解不准确
首先你提到的「两种模式都要求实现接口定义的方法」这个观察是对的,但你用来区分二者的核心标准完全错了——是否在构造函数中创建依赖类实例,只是具体编码的写法选择,和是Strategy还是Command没有任何关系。
两个模式的核心差异从来不是代码写法,而是设计意图和要解决的问题:
- Command模式的核心是把「请求/操作」本身封装成独立对象,让这个操作可以被传递、排队、延迟执行、撤销/重做、记录审计日志、组装成宏命令。它关注的是对操作本身的生命周期管理,完全不关心操作内部的逻辑怎么实现。
你完全可以把AddThenMultiplyCommand里的AddCommand、MultiplyCommand实例移到execute方法里临时创建,它依然是Command模式,不会因为实例创建位置变了就变成Strategy。文本编辑器的撤销重做、任务队列的任务单元,都是Command模式的典型场景。 - Strategy模式的核心是把「可互相替换的算法/业务规则」封装成独立对象,让调用方可以在运行时灵活切换同一场景下的不同实现逻辑。它关注的是算法的灵活替换,完全不关心这个算法能不能被撤销、排队、延迟执行。
你也完全可以把AddThenMultiplyStrategy里的Add、Multiply逻辑依赖提前放到构造函数里初始化,它依然是Strategy模式,不会因为实例创建位置变了就变成Command。电商结算的不同折扣规则、排序时选不同比较器,都是Strategy模式的典型场景。
回到你写的示例代码,两个AddThenMultiply实现的区别只有依赖初始化的位置不同,根本没有体现两个模式的核心差异:
- 如果你写这个类的目的是把「先加后乘」作为一个可记录、可回滚、可入队的操作单元使用,不管你在哪创建依赖实例,它都是Command
- 如果你写这个类的目的是把「先加后乘」作为数值计算的一种可选规则,和其他计算规则动态切换使用,不管你在哪创建依赖实例,它都是Strategy
不要把代码实现的细枝末节当成设计模式的判断标准,所有设计模式的边界都是由设计意图、解决的问题域决定的,不是由某一行代码怎么写决定的。
参考代码
interface Action { execute(currentValue: number): number; } class AddCommand implements Action { private valueToAdd; constructor(valueToAdd: number) { this.valueToAdd = valueToAdd; } execute(currentValue: number) { return currentValue + this.valueToAdd; } } class MultiplyCommand implements Action { private valueToMultiply; constructor(valueToMultiply: number) { this.valueToMultiply = valueToMultiply; } execute(currentValue: number) { return currentValue * this.valueToMultiply; } } class AddThenMultiplyCommand implements Action { private addCommand: AddCommand; private multiplyCommand: MultiplyCommand; constructor(valueToAdd: number, valueToMultiply: number) { this.addCommand = new AddCommand(valueToAdd); this.multiplyCommand = new MultiplyCommand(valueToMultiply); } execute(currentValue: number) { const newValue = this.addCommand.execute(currentValue); return this.multiplyCommand.execute(newValue); } } class AddThenMultiplyStrategy implements Action { private valueToAdd; private valueToMultiply; constructor(valueToAdd: number, valueToMultiply: number) { this.valueToAdd = valueToAdd; this.valueToMultiply = valueToMultiply; } execute(currentValue: number) { // run add const add = new AddCommand(this.valueToAdd); // run multiple const multiple = new MultiplyCommand(this.valueToMultiply); const newValue = multiple.execute(add.execute(currentValue)); return newValue; } } const add = new AddCommand(5); console.log(add.execute(6)); // 5+6 const multiple = new MultiplyCommand(5); console.log(multiple.execute(6)); // 5*6 const addThenMultiplyCommand = new AddThenMultiplyCommand(5, 6); console.log(addThenMultiplyCommand.execute(5)); // (5+5)*6 const addThenMultiplyStrategy = new AddThenMultiplyStrategy(5, 6); console.log(addThenMultiplyStrategy.execute(5)); // (5+5)*6
内容的提问来源于stack exchange,提问作者Moon
相关产品推荐
相关产品推荐

