【问题标题】:C++ policy design with variable data具有可变数据的 C++ 策略设计
【发布时间】:2015-08-04 20:38:07
【问题描述】:

关于这个话题有很多信息。这更像是一个设计问题,但我会举例说明。

假设我真的想传递一个配置文件类,它规定了用户的策略。

struct ApplicationAllowedPolicy
{
public:
    bool hasAccess() { return true; }
}

struct ApplicationProhibitedPolicy
{
public:
    bool hasAccess() { return false; }
}

template<typename ApplicationPolicy>
class Profile : private ApplicationPolicy
{
    bool hasAccess() { return ApplicationPolicy::access(); }
}

int main()
{
    Profile<ApplicationAllowedPolicy> allowed;
    Profile<ApplicationProhibitedPolicy> prohibited;

    // do something with allowed & prohibited
}

以上内容都很好,但我们假设有很多政策需要阅读。5 似乎是一个现实世界的数字,尽管可能更多。然后,假设此配置文件将应用于数百个实例,5 个策略差异很大。要启动,策略行为只会在运行时知道(从文件、数据库等读取)。这很快就会变得不可扩展,除非我完全错过了一些东西。

我想过做一个非类型模板类作为策略。

template<int N>
struct ApplicationPolicy
{
    int policy = N;
};

Profile<ApplicationPolicy<1>> allowed;
Profile<ApplicationPolicy<0>> prohibited;

我认为这确实适用于我的情况,但我想知道这是否缺少基于策略的设计要点。我无法看到这一点的优点只是让 Profile 成为一个正常的结构,并根据需要将它的数据成员设置为 true/false。

想法?

【问题讨论】:

  • 这就是您的保单的全部内容吗?它是否包含更多信息/特定行为?就像现在一样,您可以在单个布尔值上模板化您的 Profile 类并完成它。另外,我没有得到关于在运行时知道策略行为的部分......模板在编译时被实例化。
  • 对不起,如果我不清楚。是的,还有更多,但这是一个简单的例子。想象一些布尔策略,加上一些可能返回可见对象向量的策略。等等。 至于运行时,那是不好的行话。从我看到的许多示例中,使用策略的最终类似乎相当静态 - 在一个主要的想法中创建。我需要一些更有活力的东西。出门在外,但如果需要,稍后会编辑。

标签: c++ templates policy-based-design


【解决方案1】:

当类的行为因策略而发生显着变化时,基于策略的设计非常有用。例如,假设您希望您的类在多线程和常规上下文中都使用。然后你可以把它作为一个线程策略来实现:

class SingleThreadedPolicy { /* ... */ }; // lock() does nothing
class MultiThreadedPolicy { /* ... */ }; // lock() actually locks

template<class T, class ThreadingPolicy>
class Queue {
    ThreadingPolicy threadPol_;
    // ...
    T pop() {
       threadPol_.lock();
       // remove an element from the queue
       threadPol_.unlock();
       return element;
    }
};

现在,实现相同结果的另外两种方法是使用(多重?)继承或在对象中设置标志并编写大量 ifs。如果您有多个策略(例如存储、所有权等),第一个选项很快就会失效。第二个选项会导致代码无法维护。

因此,如果您的班级需要许多正交移动部件,基于策略的设计是一个不错的选择,而且它比其他方法更具可扩展性。

但是,您的示例似乎并不真正需要这种方法。访问似乎是它不可或缺的一部分:如果您要在代码中调用hasAccess(),您可以安全地将其替换为布尔变量。

【讨论】:

  • 根据上面的评论,这只是一个简单的说明。策略可能会返回允许客户端查看/编辑的某种类型的数据容器,而不是应用程序的布尔值。如果他们无权访问,它可能会返回一个空容器,或者类似的东西。我不打算实施的部分是想象我有多个用户的数据库记录,每个用户将根据用户使用多个策略。如何在没有大量 if 语句的情况下实例化我的类?
  • 我认为你走错了路。要回答您的问题,您将使用 Builder 模式,分阶段构建有关对象的信息,然后根据该信息实例化适当的对象(即通过将输入集映射到工厂函数)。它将返回一个指向抽象基类的智能指针,您可以从中派生策略模板。但是,对于配置文件类,您选择了错误的设计。
  • 我不太明白您将如何将配置文件分解为适当的策略。一个类最好有单一的职责,就像一个函数一样。因此,同样,如果不同的人对某些数据有不同的访问权限,请提供一个非成员函数,该函数将您的个人资料作为参数并返回他们可以看到的任何内容。也许我错了——你能提供一份你正在考虑的所有政策的清单吗?
  • 越想越觉得你是对的。这就是为什么我想大声思考这个问题。至于政策清单,我试图在深入研究之前弄清楚这一点的另一个原因可能会变得相当大。 (项目仍处于起步阶段)。实际上,它可能是一个包罗万象的机制,决定了事物的行为方式。它连接的位置,读取权限,写入权限,甚至可能还有其他一些设置。为你的帮助干杯。我会继续将此标记为已回答,因为它确实回答了我的问题。
【解决方案2】:

如果您想在运行时改变行为,请使用策略模式而不是基于策略的设计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 2013-05-17
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    相关资源
    最近更新 更多