2016-04-29 48 views
0

我有一个“项目”,其数据可以用3种方式表示。我可以以运行成本从一种表示转换为其他表示。一旦我做了转换,我想保留新的表示。无需“修改”核心数据,任何数据表示都可以转换为其他数据。由于运行时成本,我想要一个包含3个数据表示的类。在任何时候,其中1到3个将是有效的。具有多个表示的项目的C++设计模式

这真正的一点是因为它也有访问方法,用户可以在这里访问某些东西。这可以从1个或更多的表示中获得。例如,你可以从representation1得到“范围”,从表示2或3得到“范围”。

我的解决方案是创建具有3个表示形式的类作为成员数据(以及如何知道它们是否有效)。然后我创建了一个getRange()方法,该方法在内部知道它需要哪个表示,并在必要时创建它。这工作正常,解决了我的所有问题,除了get方法不能是const。

所以这个解决方案的真正问题是,即使是这个类的“常量”实例也不是真正的常量,因为它在内部可能会创建其他表示。但它确实是“不变的”,因为改变表示不会修改核心数据。

是否有C++设计模式可以帮助这个类?有什么建议么?

回答

3

我的解决方案是创建类与3表示作为成员数据(以及如何知道它们是否有效)。然后我创建了一个getRange()方法,该方法在内部知道它需要哪个表示,并在必要时创建它。这工作正常,并解决我所有的问题除了get方法不能是const

这是指定的mutable类型的目的!为了能够同时还具有const方法来更新内部表示,使表示属性mutable

struct A { 

    int get_range() const { 
     if (!_repr2.is_valid()) { 
      _repr2 = Repr2(_repr1); // I am in a const method, but still 
            // I can update a mutable attribute 
     } 
     return _repr2.get_range(); 
    }  

private: 
    mutable Repr1 _repr1; 
    mutable Repr2 _repr2; 
}; 

Here是两种表述一个完整的例子,它使用std::unique_ptr存储表示这样你就可以很容易地检查如果一个人不在场。

+0

这太棒了。正是我想要的。比我预期的要容易得多!谢谢。 – user3375624

1

根据霍尔特的回答,mutable是这里需要的主要东西。您还可以从boost::optional<ReprX>中受益,用于存储表示。这有助于'知道自己是否有效'的一部分:

struct A { 

    int get_range() const { 
     if (!_repr2) { 
      _repr2 = Repr2(*_repr1); 
     } 
     return _repr2->get_range(); 
    }  

private: 
    mutable boost::optional<Repr1> _repr1; 
    mutable boost::optional<Repr2> _repr2; 
}; 
+0

我也喜欢这个!我的代码已经使用boost,所以我会这样做。谢谢! – user3375624

+0

boost :: optional的另一个好处是它不调用类的默认构造函数。我不得不使用它,因为没有它的运行速度显着下降。事实证明,这些表示的默认构造函数(来自我无法控制的库)非常慢,实际上影响了运行时速度。通过切换使用boost ::可选,它解决了这个问题。太好了! – user3375624