将任务拆分为类别

时间:2017-01-04 15:32:29

标签: c++ algorithm design-patterns

我有一个类(让我们称之为检查器)和不同类的执行任务的类(让我们称之为任务)。每个任务属于几个类别

每个任务都会运行,并且在某些时候会询问检查者是否允许他们做某事。检查员根据系统状态和他们的类别回答。任务可以分为多个类别

你会如何实现? (cpp但我并不认为它的语言特定)。

我在考虑在每个任务中添加一个类别列表,并且有一个函数可以获取一个类别,并在任务属于它时回答。

class checker {
    bool is_allowed(Task * task);
}

class Task
{
    bool is_belongging_to_category(Category cat);
    void some_task_to_do()
    {
        ...
        if (checker::is_allowed(this)) { ....}
        else {....}
    }
}

有没有更好的方法来解决这个问题?也许一些已知的设计模式......

4 个答案:

答案 0 :(得分:0)

您可以制作一个矢量来存储所有可能允许的选项。您可以使用参数字符串创建一个名为IsAllowed的bool函数(就像您所拥有的那样),并检查它将要执行的选项是否允许。如果没有,则返回false。这只是我的想法。当然,实现这一目标的方式有很多种。如果你想要多种选择。然后你可以制作一个2d向量,看看相应的行是否有任何选项。祝你好运!

答案 1 :(得分:0)

如果您事先知道最大类别数,我建议您使用Bit Flags来执行此操作。

enum Category {
    CATEGORY_A = 1,
    CATEGORY_B = 1 << 1,
    CATEGORY_C = 1 << 2,
    CATEGORY_D = 1 << 3,
};

class Task {
  int32_t categories_;
public:
  Task() : categories_(0) {}

  void add_category(Category cat) {
    categories_ |= cat;
  }

  void run() {
    checker::can_run(categories_);
  }
} 

这允许同时测试多个类别:

namespace checker {

bool can_run(int32_t categories) {
  int32_t cannot_run_right_now = CATEGORY_A | CATEGORY_C;   

  if(categories & cannot_run_right_now != 0) {
     return false;
  }
  ...
}
}

答案 2 :(得分:0)

嗯,这取决于。如果您100%确定您知道有多少类别,并且这不是一个巨大的数字,那么您可以将此信息存储为整数。如果第n位为1,则任务属于第n类。然后取决于系统的状态,您可能会创建另一个将用作掩码的整数。最后,您只需执行一些位AND(掩码和类别!= 0)操作,以确定任务和掩码是否共享公共位。

另一方面,如果将有未知数量的类别,您可以只列出它所属的类别。制作[SYSTEM_STATE] =&gt;的字典[CATEGORIES_AVAILABLE]并检查

  bool is_allowed(Task * task){
    foreach (Category sysC in stateCategories[sys.GetState()])
    {
       foreach (Category taskC in task.GetCategories()) 
       {
         if(sysC == taskC) return true;
       }
    }
    return false;
    }

对于大量类别来说,这当然会很慢。 你可以通过使这个类别列表成为另一种数据结构来改进这种方法,其中搜索不是O(n),使得代码看起来像这样:

  bool is_allowed(Task * task){
    foreach (Category sysC in stateCategories[sys.GetState()])
    {
       if task.GetCategories().Contains(sysC) {
         return true;
       }
    }

取决于

答案 3 :(得分:0)

这看起来像有问题的设计。你正在把任务作为对象。

假设您的任务是:饮用 Be_Merry

如果你将这些任务中的每一个都作为对象,他们就必须保持对他们操作的实际个体的引用,然后当条件满足时,他们需要修改给定个体的状态。

这违反了Object Oriented Design,将对象定义为:

  

数据结构与作用于数据的方法或函数的紧密耦合或关联

请注意,您已从对象中拆分“作用于数据的方法或函数”。相反,你应该建模对象杰克吉尔,其中方法饮料,和 BeMerry

checker而言,它是否被分割将取决于您使用的是push还是pull coding。如果您正在进行推送编码,那么检查器只是 Jack Jill 的行为属性的保留区域,在这种情况下,属性应该被推送到杰克吉尔而不是checker。如果它们是所有 Jack Jill 对象的属性,请使用static属性。但是,如果您使用的是拉码,那么在您尝试执行任务之前,该信息将不可用。在这种情况下,checker应该是在执行任务的过程中 Jack Jill 访问的单身人士。

修改

Your comment揭示了设计中的进一步悲剧。看起来好像你已经开始忙于等待checker忙碌的一堆线程。这表明您需要使用拉码。您杰克 Jill 对象需要维护他们积极参与的任务的布尔值,例如m_is_going_to_school,然后checker获取这种条件会阻止您在设计中忙碌等待,而是启动goToSchool方法。