我有一个类(让我们称之为检查器)和不同类的执行任务的类(让我们称之为任务)。每个任务属于几个类别
每个任务都会运行,并且在某些时候会询问检查者是否允许他们做某事。检查员根据系统状态和他们的类别回答。任务可以分为多个类别
你会如何实现? (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 {....}
}
}
有没有更好的方法来解决这个问题?也许一些已知的设计模式......
答案 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
方法。