使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

时间:2022-04-15 03:17:59

使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

有这样一个可编程的新型遥控器, 它有7个可编程插槽, 每个插槽可连接差此外家用电器设备. 每个插槽对应两个按钮: 开, 关(ON, OFF). 别的还有一个全局的打消按钮(UNDO).

此刻客户想使用这个遥控器来控制差别厂家的家用电器, 例如电灯, 热水器, 风扇, 音响等等.

客户提出让我编写一个接口, 可以让这个遥控器控制插在插槽上的一个或一组设备.

看一下目前各家厂商都有哪些家用电器??:

使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

问题来了, 这些家用电器并没有配合的标准....几乎各自都有本身的一套控制要领.. 而且以后还要添加很多种家用电器.

设计思路

那就需要考虑一下设计方案了:

首先要考虑疏散存眷点(Separation of concerns),  遥控器应该可以解释按钮行动并可以发送请求, 但是它不应该了解家用电器和如何开关家用电器等.

但是目前遥控器只能做开关成果, 那么怎么让它去控制电灯或者音响呢? 我们不想让遥控器知道这些具体的家用电器, 更不想写出下面的代码:

if slot1 == Light then Light.On() else if slot1 == Hub....

说到这就不得不提到命令模式(Command Pattern)了.

命令模式允许你把行动的请求者和行动的实际执行者解耦. 这里, 行动的请求者就是遥控器, 而执步履作的东西就是某个家用电器.

这是怎么解耦的呢? 怎么可能实现呢?

这就需要引进"命令东西(command object)"了. 命令东西会封装在某个东西上(例如卧室的灯)执行某个行动的请求(例如开灯). 所以, 如果我们为每一个按钮都筹备一个命令东西, 那么当按钮被按下的时候, 我们就会挪用这个命令东西去执行某些行动. 遥控器自己并不知道具体执行的行动是什么, 它只是有一个命令东西, 这个命令东西知道去对哪些电器去做什么样的操纵. 就这样, 遥控器和电灯解耦了.

一个命令模式的实际例子

一个快餐厅:

使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

客户给处事员订单, 处事员把订单放到柜台并说: "有新订单了", 然后厨师凭据订单筹备饭菜.

让我们仔细分析一下它们是怎么交互的:

使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

客户来了, 说我想要汉堡, 奶酪....就是创建了一个订单 (createOrder()).

订单上面写着客户想要的饭菜. 

处事员取得订单 takeOrder(), 把订单拿到柜台喊道: "有新订单了" (挪用orderUp())

厨师凭据订单的指示把饭菜做好 (orderUp()里面的行动). 

分析一下这个例子的角色和职责:

订单里封装了做饭菜的请求. 可以把订单想象成一个东西, 这个东西就像是对做饭这个行动的请求. 并且它可以来回通报. 订单实现了一个只有orderUp()要领的接口, 这个要领里面封装了做饭的操纵流程. 订单同时对行动实施者的引用(厨师). 因为都封装了, 所以处事员不知道订单里面有啥也不知道厨师是谁. 处事员只通报订单, 并挪用orderUp().

所以, 处事员的事情就是通报订单并且挪用orderUp(). 处事员的取订单takeOrder()要领会传进来差此外参数(差别客户的差别订单), 但是这不是问题, 因为她知道所有的订单都撑持orderUp()要领.

厨师知道如何把饭做好. 一旦处事员挪用了orderUp(), 厨师就接管了整个事情把饭菜做好. 但是处事员和厨师是解耦的: 处事员只有订单, 订单里封装着饭菜, 处事员只是挪用订单上的一个要领而已. 同样的, 厨师只是从订单上收到指令, 他从来反面处事员直接接触.

项目设计图

回到我们的需求, 参考快餐店的例子, 使用命令模式做一下设计:

使用 C# (.NET Core) 实现命令设计模式 (Command Pattern)

客户Client创建了一个命令(Command)东西. 相当于客人拿起了一个订单(点菜)筹备开始点菜, 我在琢磨遥控器的槽需要插哪些家用电器. 命令东西和接收者是绑定在一起的. 相当于菜单和厨师, 遥控器的插槽和方针家用电器.

命令东西只有一个要领execute(), 里面封装了挪用接收者实际控制操纵的行动. 相当于饭铺订单的orderUp().

客户挪用setCommand()要领. 相当于客户想好点什么菜了, 就写在订单上面了. 我也想好遥控器要控制哪些家电了, 列好清单了.