0

我想要一个类模板template<std::size_t N> Shape,其中模板参数N代表Shape. 应该有数量有限的预定义Shapes,例如Shape<2> SQUARE,Shape<3> CUBEShape<3> SPHERE。将来我可能会添加更多预定义Shape的 s。

我希望Shape对象仅可构造为任何预定义Shape的 s。由于这些预定义Shapes 的属性始终保持不变,因此最好只将它们存储一次,并让新Shape对象引用它们。

此刻,我有以下实现:

// Flag for the possible shapes
enum class Tag
{
    SPHERE,
    CUBE,
    SQUARE
};

template<std::size_t N>
class Shape
{
public:
    // Predefined shapes.
    static const Shape<3> SPHERE;
    static const Shape<3> CUBE;
    static const Shape<2> SQUARE;
    // Information stored about the given shapes
    const Tag tag; // tag specifying the shape
    const double v; // Shape volume/area
    const std::array<double, 2*N> surrounding_box; // Storing intervals for a surrounding box
    //... Some other information that depends on template parameter N
private:
    // Private constructor. This prevents other, unintended shapes from being created
    Shape(Tag tag, double v, const std::array<double, 2*N> surrounding_box):
            tag{tag}, v {v}, surrounding_box {surrounding_box} {};
};

// Initialization of predefined shape: SPHERE
template<std::size_t N>
const Shape<3> Shape<N>::SPHERE(Tag::SPHERE, 3.0,{{0.0,2.7,0.0,2.7,0.0,2.7}});

// Initialization of predefined shape: CUBE
template<std::size_t N>
const Shape<3> Shape<N>::CUBE(Tag::CUBE, 1.0,{{0.0,1.0,0.0,1.0,0.0,1.0}});

// Initialization of predefined shape: SQUARE
template<std::size_t N>
const Shape<2> Shape<N>::SQUARE(Tag::SQUARE, 1.0,{{0.0,1.0,0.0,1.0}});

这个实现有几个问题:

  • 的每个实例都Shape包含所有预定义的 s(如本问题Shape的评论中所指出的);
  • Shape在创建的每个实例之前,Shape都会复制预定义 s 的内容;
  • 甚至一个Shape<3>对象也包含Shape<2> SQUARE.
  • ...

我想知道实现上述目标的更好设计模式是什么。我正在考虑使用Tag作为构造函数参数并使用某种工厂。但是,由于模板的复杂性以及我只希望预定义Shape的 s 是可构造的,我无法正确获取实现细节。

4

1 回答 1

1

工厂模式是您所需要的。它将实例的创建委托给另一个类。

有多种实现方法,您可以根据问题的复杂性选择抽象级别。

这是一个基本示例

template<std::size_t N>
class Shape
{
    friend class ShapeFactory;
public:
    // Information stored about the given shapes
    const Tag tag; // tag specifying the shape
    const double v; // Shape volume/area
    const std::array<double, 2*N> surrounding_box; // Storing intervals for a surrounding box
    //... Some other information that depends on template parameter N
private:
    // Private constructor. This prevents other, unintended shapes from being created
    Shape(Tag tag, double v, const std::array<double, 2*N> surrounding_box):
            tag{tag}, v {v}, surrounding_box {surrounding_box} {};
};

class ShapeFactory
{
public:
    // return value optimization
    static Shape<3> createSphere()
    {
        return Shape<3>(Tag::SPHERE, 3.0,{{0.0,2.7,0.0,2.7,0.0,2.7}});
    }

    static Shape<3> createCube()
    {
        return Shape<3>(Tag::CUBE, 1.0,{{0.0,1.0,0.0,1.0,0.0,1.0}});
    }

    static Shape<2> createSquare()
    {
        return Shape<2>(Tag::SQUARE, 1.0,{{0.0,1.0,0.0,1.0}});
    }
};

由于这些预定义 Shape 的属性始终保持不变,因此最好只将它们存储一次,并让新的 Shape 对象引用它们。

如果您严格要使用这种方法,可以参考原型模式

于 2018-10-15T10:11:53.523 回答