具有 Boost 和外部数据源的享元

Posted

技术标签:

【中文标题】具有 Boost 和外部数据源的享元【英文标题】:Flyweights with Boost and external data sources 【发布时间】:2012-01-13 16:39:16 【问题描述】:

也许有一个我没有看到的简单方法,所以希望有人可以向我解释。

假设我有一堂课:

class A 
public:
  const double parameter;
  const std::string name;
  const std:: string fileName;

  A(const double parameter, const std::string name, const std::string fileName) : 
      parameter(parameter), name(name), fileName(fileName) ; 
;

该类的生成器是:

class AReader 
public:
  ifstream dataFile;
  AReader(const std::string filename);
  A* readObject(const std::string objectName);
;

我想使用boost::flyweight 来处理这些A 对象,因为可能会有数百万个对它们的引用,而实际上它们包含大量数据。它们将在namefileName 上一起进行哈希处理。

我需要什么来完成这项工作?我需要boost::flyweight 来调用AReader.readObject 并散列/存储生成的A 类。

AReader 是否需要成为完整工厂并用作定制工厂?或者是否可以在享元中使用默认工厂并以某种方式使用AReader 生成A 实例(而不是实现工厂所需的整个存储模式),也许可以通过将AReader 实例作为参数在蝇量级的东西?或者是否有可能从外部数据源获取const 公共变量(即一旦设置,它们就不会改变)而不求助于第二类?

编辑

我也愿意接受其他不使用 Boost 的建议。我当然可以编写自己的轻量级实现,或者如果有更适合的任何其他模式。但是,如果我可以使用已经存在的东西,那将是最好的。无论什么都能最大限度地减少我需要编写的代码量,因为与往常一样,截止日期很短。

【问题讨论】:

【参考方案1】:

我没有使用过 Boost::flyweight,但至少从外观上看,键必须是 Assignable(除了 EqualityComparableHashable)。对于您的const 成员,您输入的显然是不是 Assignable。从外观上看,如果您有密钥提取器,则不必将其设为Assignable。使用密钥提取器,密钥只需为Assignable

【讨论】:

处理将A 放入flyweight 需要做的事情(键提取器而不是可分配的),但这是使用生成A 的帮助器类的唯一方法。一个成熟的工厂供享元使用(实现所需的存储和其他方法)?【参考方案2】:

在您的情况下使用享元的基本方法是让 readObject 返回一个享元。 在内部,readObject 创建一个全新的对象,当您创建相应的享元对象时,它会检查该对象是否已经在享元存储中。如果是这样,它将删除您的新对象,并返回一个引用存储中对象的享元。如果没有,它会将新对象添加到其池中。

现在,这应该很容易实现,但根据您的用例可能效率低下。为获得更好的性能,您可以使用key_value 功能,该功能允许您通过对象的键引用对象,并且仅在存储中不存在它们时才创建它们。

【讨论】:

【参考方案3】:

虽然key_value Flyweight 似乎符合要求,但似乎有一个小问题。 您应该能够通过仅使用密钥类型的一个参数 (key_value flyweights) 来构造 key_value Flyweight。因此,要使其与您想要的密钥(文件名+名称)一起使用,您必须将这 2 个字段合并为一个(tuple?甚至不确定这是否可行。)

假设您有兴趣以最少的工作获得最大的收益,为什么不只是 Flyweight 类中的字符串,如 Flyweight Basics 中所示?

这意味着A 对象不会按照您想要的方式进行散列,但字符串很容易被加权,并且这些似乎是您的内存问题字段。 (除非这是过于简单化)

【讨论】:

以上是关于具有 Boost 和外部数据源的享元的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript设计模式中的享元模式

JavaScript设计模式中的享元模式

设计模式之享元模式与组合模式详解和应用

结构型模式—享元模式

将 Boost 享元与共享内存一起使用

设计模式---享元模式