【设计模式 13】命令:覆水能收

这一课讲命令模式。什么在变:决策需要记录、排队、撤销。怎么挡:把决策封装成命令对象,可执行可回滚。

林衍那次决策失误,后来集团内部管它叫"黑色十月"。

起因是赵闯带回来一条消息:一家新晋竞争对手拿到了十亿级融资,开始用补贴战打市场。对方的核心策略简单粗暴------同品质产品低于成本价销售,靠融资的钱烧出市场份额。

林衍在战略会上拍板:应战。全线产品降价百分之二十,抢在对手前面把价格打到底。

陈敏当时就反对:"百分之二十?你知道这意味着什么吗?全年毛利率从百分之三十二降到百分之十四。如果我们抢不到足够的市场份额来弥补,这一年的利润就白干了。"

林衍说:"战争打的是速度。先抢份额,利润明年追回来。"

赵闯全力执行。降价通知发给了全部经销商,终端价格更新到所有渠道,电商页面同步改价,返点方案重新计算。整个集团像一台机器一样,用了四十八小时完成了全面降价。


两周后,数据出来了。

陈敏把报表放在林衍桌上,没说话。林衍看了五分钟。

销量增长了百分之十一。不是百分之三十,不是百分之五十。百分之十一。

利润呢?少了十九亿。

更糟的是,竞争对手根本没跟降。他们拿了融资不假,但补贴战的消息是赵闯从行业饭局上听来的二手情报。对方拿了钱是用来建产线、做研发的,不是用来烧补贴的。

赵闯的情报错了。林衍基于错误情报做了决策。而决策已经执行了两周,不可逆转。

林衍找陈敏:"能撤回吗?"

陈敏看着他,像在看一个问"能不能把倒出去的水收回来"的人。

"价格已经通知了全部经销商。终端价格已经改了。返点已经结算了一期。你现在涨回去,经销商觉得你在玩他们。不涨回去,十九亿已经没了。"

林衍那天晚上一个人在办公室坐到凌晨两点。


第二天早上,林衍叫了一个会。不是复盘会------复盘以后再做。他要的是一件更根本的东西。

"如果下次我做了一个决策,执行了一半发现是错的,我能不能撤回?"

陈敏说:"那要看决策执行到了哪一步。如果只是内部通知,可以撤。如果已经到了终端,撤不了。"

"如果到了终端,但是刚到呢?比如只执行了一天?"

"理论上可以改回来。但你要知道改回来需要做哪些事------通知经销商、改价格、调返点、更新页面------跟执行决策的时候一样,反过来做一遍。"

林衍在白板上写了一行字:每一个重大决策,执行前必须封装成可撤销的操作。

"什么叫封装成可撤销的操作?"

林衍说:"就是每一次决策不是'直接执行',而是变成一个指令。指令包含三样东西:执行动作、撤销动作、执行记录。执行的时候做'执行动作',撤回的时候做'撤销动作'。不管决策涉及到多少个部门、多少个系统,撤回就是调一下'撤销'。"

陈敏问:"那如果执行了一半呢?比如经销商已经收到通知了,但终端还没改价?"

"指令要记录执行到哪一步了。撤回的时候从当前步骤往回退。不是一刀切回原点,是逐步回滚。"

林衍在白板上写的那个制度------每一个决策封装成可撤销的指令------在程序设计里有一个名字:命令模式

把"做什么"封装成一个命令对象,调用方只持有命令。命令可以排队、存储、撤销。覆水,能收。
stores history
<<interface>>
Command
+execute()
+undo()
PricingDecision
-amount: float
-receiver: BusinessUnit
+execute()
+undo()
ExpansionDecision
-region: string
-receiver: BusinessUnit
+execute()
+undo()
DecisionLog
-history: Command\[\]
+submitCommand(cmd: Command)
+undoLast()
BusinessUnit
+applyPriceChange(amount)
+revertPriceChange(amount)
+applyExpansion(region)
+revertExpansion(region)

林衍的决策日志就是 DecisionLog,每一条定价或扩张指令都是一个 Command,错了就调 undo 回滚。

孙子说:"先为不可胜,以待敌之可胜。"先让自己处于不会输的位置,再等赢的机会。命令模式做的就是"先让自己不会输"------每一个决策都带着退路,错了能撤,不至于一错到底。


本文所有人物、情节、公司名均为虚构,如有雷同,纯属巧合。

相关推荐
杨充21 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充21 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式