4

我正在尝试找到一种优雅的方式来实现易于维护的决策算法,因为决策条件可能经常变化。

我将在这里尝试更具体的示例:

假设我正在尝试管理餐厅厨房中的烹饪厨师团队。

每个厨师都知道如何烹制 3 种派:苹果派、南瓜派和覆盆子派以及 2 种比萨:奶酪比萨和培根比萨。他们都知道如何烹饪所有东西。

现在,我想向这些主管发送订单,告知客户即将发生的事情。

条件是:

酋长一次只能做一个馅饼。例如,如果我命令厨师做苹果派,我不能命令他做覆盆子派或南瓜派,除非苹果派做好或我发送了取消苹果派的请求。

考虑到为不同的客户,我可以要求厨师一次最多做 5 个比萨饼。

我想创建一个算法,返回我被允许发送给特定厨师的一组订单,关于他已经在做什么。

我正在使用 c++。我可以写一个简单的 switch/case 语句,但是如果条件改变或添加新的馅饼,维护将并不容易,所以......

我有点卡住了,真的不知道如何封装条件和决策以减少条件之间的耦合,并允许在馅饼烹饪条件下轻松维护。

你将如何处理复杂的决策算法实现?

4

2 回答 2

4

我可以写一个简单的 switch/case 语句,但是如果条件改变或添加新的馅饼,维护将并不容易,所以......

我有点卡住了,真的不知道如何封装条件和决策以减少条件之间的耦合,并允许在馅饼烹饪条件下轻松维护。

你将如何处理复杂的决策算法实现?

从 switch/case 到可维护的 OOP 的经典更改/重构是用抽象类专业化/实现替换每个条件和操作。

旧代码:

variable_t variable; // initialized elsewhere
switch(variable) {
case value1:
    do_action1();
    break;
case value2:
    do_action2();
    break;
// ...
}

新代码:

struct Actor // actor is your "abstract chef"
{
    virtual ~Actor();
    virtual bool matches(variable_t const v) const = 0;
    virtual void do_action() = 0;
};

现在,对于每个动作和条件组合,您创建一个专业化:

struct SweedishChef: public Actor {
    bool matches(variable_t const v) const override
    {
         return v == 1;
    }

    void do_action() override
    {
         std::cerr << "bork! bork!\n";
    }
};

有了这个,客户端代码不再有任何硬编码。

客户端代码初始化:

std::vector<std::unique_ptr<Actor>> actors;
actors.emplace_back( new SweedishChef{} };
// adding a new type of chef simply means adding _one_ line of
// code here, for the new type

决策代码(替换旧switch代码):

// using std::find, begin, end
variable_t variable; // initialized elsewhere
const auto chef = find(begin(actors), end(actors),
    [&v](const std::unique_ptr<Actor>& a) { return a->matches(v); });

if(chef != end(actors))
    chef->do_action();
else
{
    // here goes whatever was in the default part of the switch code
}

从维护和可测试性的角度来看,这段代码更易于维护:

  • 添加新厨师时,客户端代码的更改很少

  • 厨师和命令之间的交互已在界面后面形式化(并冻结)

  • 每个条件/动作都可以(并且应该)单独测试

  • 调度机制可以单独测试(并使用模拟注入的actors,以应对各种情况)。

  • 初始化机制可以单独测试

于 2014-09-29T09:46:57.390 回答
-1

不,编码太多了。只计算符号。这种编码不能保证为“new SwedishChef{}”释放清晰的内存。并且客户端大小在变量声明中变得更长。

于 2014-09-29T10:12:23.117 回答