在c++中使用映射器处理派生类的创建



我正在阅读Martin Fowler关于对象关系结构模式的PoEAA。作为学习它们的同时做的一个项目,我想用c++构建一个小型电子商务系统。我不知道如何从映射器返回对象。

我有一个Product基类,它有派生类HatShirtProducts有一个type成员来标识它们是哪个派生类。我也有一个ProductMapper类,具有派生类HatMapperShirtMapper,所有这些都实现了一堆查找器方法,让我尝试检索某些帽子和衬衫。

class Product
{
    unsigned long long int id;
    std::string name;
    unsigned int type;
};

// Derived classes don't necessarily have the same members.
class Hat : public Product
{
    unsigned char fitted;
    unsigned char color;
    unsigned char style;
};
class Shirt : public Product
{
    unsigned char size;
};

在我的应用程序的逻辑部分,我将实例化这些映射器和检索产品是我有麻烦的地方。我可以实例化HatMapper并拉回Hat对象而没有任何问题,ShirtMapperShirt对象也是如此。这些模式在这些情况下工作得很好(特别是我使用类表继承,即一个包含产品数据的产品表,一个包含特定于帽子的数据的帽子表,一个包含特定于衬衫的数据的衬衫表)。

我的问题是,如果我想检索所有产品,包括帽子和衬衫,我该怎么办?我可以实例化一个ProductMapper并获取所有产品数据,但这似乎是错误的方法,因为我必须遍历我检索的所有Products,并根据程序逻辑部分中的HatsShirts的类型构建它们。此外,当我添加新产品类型时,我必须修改任何以这种方式处理这种情况的代码。似乎坏。

Fowler的书中有一些使用派生映射器的基本映射器的映射器的例子,这在我看来是完全错误的(每次添加新产品时都必须修改基本映射器,不是很好)。下面是一个简单的例子:

class ProductMapper
{
    unsigned long long int productId;
    unsigned long long int productType;
    HatMapper * hm;
    ShirtMapper * sm;
    Product * FindById(unsigned long long int id)
    {
        // Query database for data.
        if (this->productType == PRODUCT_TYPE_HAT)
        {
            return hm->FindById(id); // Hat object.
        }
        else if (this->productType == PRODUCT_TYPE_SHIRT)
        {
            return sm->FindById(id); // Shirt object.
        }
        return NULL;
    }
};

下面是我如何在程序的逻辑部分使用它。书中没有提供这样的例子:

ProductMapper * pm = new ProductMapper();
Product * p = pm->FindById(1); // It's a Product, but a Hat or Shirt?
// Have to check type since a Product was returned.
switch (p->type)
{
    case PRODUCT_TYPE_HAT:
    {
        Hat * h = (Hat) p;
        break;
    }
    // Etc. Modify this every time a new product type is added or removed.
}

这将引入循环依赖。此外,假设我以某种方式消除了循环依赖,HatMapperShirtMapper类的结果是Hat对象和Shirt对象。因此,当我从ProductMapper返回时,我将进行向下转换,因此我必须再次在我的逻辑中操作结果,这再次引入了在引入新产品类型时修改代码的问题。

我不知道该怎么办。在一个完美的世界里,我希望有一个Product类和一个ProductMapper类,我可以快速扩展这两个类,引入新的产品类型,而不必修改现有的代码(至少太多)。

我希望能够从PoEAA中使用这些模式,它们看起来很好也很有用,但我不确定这是否只是我不能在c++中做的事情,或者我错过了一些阻止我这样做的事情。其他模式和方法也非常受欢迎。

感觉Type Object模式在这种情况下可以有所帮助,我知道链接是关于游戏编程的,但它足以将模式应用于其他领域。

现在的问题是,如果你想添加产品,你必须添加几个类,正如你注意到的那样,这可能变得难以维护。

编辑:也许你可以使用类似的东西(代码是c++ 11来简化示例):

class ProductProperty
{
    typedef std::map<std::string, unsigned char> PropertyMap;
    PropertyMap properties;
    public:
    ProductProperty(std::initializer_list<PropertyMap::value_type> il):
        properties(il)
    {}
    // Use of at() is intended to only deal with the defined properties
    const PropertyMap::value_type::second_type& 
        get(const PropertyMap::value_type::first_type& prop) const 
    { 
        return properties.at(prop); 
    }
    PropertyMap::value_type::second_type& 
        get(const PropertyMap::value_type::first_type& prop) 
    { 
        return properties.at(prop); 
    }
};
// Some helpers to illustrate
std::shared_ptr<ProductProperty> makeHatProperty()
{
    return std::make_shared<ProductProperty>(
        ProductProperty{
            {"fitted", ***whatever**},
            {"color", ***whatever**}, 
            {"style", ***whatever**}
        });
}
std::shared_ptr<ProductProperty> makeShirtProperty()
{
    return std::make_shared<ProductProperty>(
        ProductProperty{{"size", ***whatever**}}
        );
}
class Product
{
    unsigned long long int id;
    std::string name;
    unsigned int type;
    std::shared_ptr<ProductProperty> properties;
    public:
    Product(std::shared_ptr<ProductProperty> props):
        properties(props)
    {}
    // Whatever function you need to get/set/check properties
};

相关内容

  • 没有找到相关文章

最新更新