5

我有一个设计问题,实际上并不复杂,但我想找到一种优雅的方法来解决它。我想到了这个:

问题:我有一个类 A 初始化并保留 B 的集合

B 只是一个接口,必须实现(所以我们有 C、D、E 等类)。

在构造函数 A 中接收一堆数据集,并且必须在给定每个数据集的情况下初始化 B 中的一些(也是相同或不同类的许多不同实例化)。我希望 A 不知道 B 的任何实现。

我有几个可行的解决方案,但我正在考虑一种“构造函数中的委托”。例如:

1. for each dataset, ds
2.   for each implementation of B, bi
3.     try to instantiate bi(ds)
4.       if success (means no exception)
5.         keep reference

这是因为我用来检查 bi 是否与初始化非常相似的数据和微积分,并且在性能关键的应用程序中,我想避免这样做两次或在集合类中进行。
这会非常好,但显然问题出在第 2 行......
以及对实际上不是异常的事情使用异常的怀疑。(第 4 行)
那么应该是什么模式
- 让我评估数据并构建所有内容。
- 避免创建几个“架构类”我想避免这样一个简单任务的类爆炸(在使用以下设计模式 java 风格原则夸大其词时很典型)。- 尽可能快。
- ...优雅:)

4

3 回答 3

2

答案是基于我现在的直觉,所以它可能并不完美,但另一方面,大多数设计解决方案都不是。

我只会创建一个额外的类,称之为工厂或类似的东西。然后通过这个类运行所有的结构。它应该能够在运行时(通过在程序开始时运行回调),或者甚至更好地通过可变参数模板特征,使用 B 派生的可能实例进行初始化。

template<class ... RegisteredBImplementations>
class CFactory
{
    B* Create (dataset const& d)
    {
        // some magical meta-ifs to create compile time conditions
        // or for (auto& registered_type : registered types), and then choose one
        return new T(d);
    }
}

然后,A 可以使用此类的实例来正确初始化它的指针:

for (auto& dataset : datasets)
{
    m_BPtrs.emplace_back( std::unique_ptr<dataset> (m_FactoryInstance.Create(dataset)) );
}

该解决方案的要点是 A 类有效地管理“B”对象,将它们的正确构造留给其他类。它们实际上是分开的,并且添加新B实现意味着仅在 中进行更改CFactory,而不是在 中进行更改A

于 2012-08-28T10:01:56.970 回答
1

最简单的解决方案是委托给工厂方法。

std::unique_ptr<B> build(DataSet const& ds) {
    if (ds.property() == value) {
        return std::unique_ptr<B>(new D(ds));
    }
    return std::unique_ptr<B>(new C(ds));
}

那么A只需要依赖于build.

于 2012-08-28T12:51:50.643 回答
1

您的伪代码提出了一个解决方案:您的使用bi只不过是一个工厂函数,它将 adataset作为输入并返回 aB*作为输出。所以,你真的只需bi要从对象集合中获取std::function<B* (dataset)>

很容易要求这些工厂只是“条件”工厂:有时它们返回有效对象,有时它们不返回,nullptr而是返回。这将使您避免异常,并且更忠实于您的使用意图。

于 2012-08-28T14:01:48.150 回答