我现在正在阅读 Martin Fowler 关于对象关系结构模式的 PoEAA。作为一个学习它们的项目,我想我会用 C++ 构建一个迷你电子商务系统。我无法弄清楚如何从映射器返回对象。
我有一个Product
基类,它有派生类Hat
和Shirt
. Products
有一个type
成员来标识它们是哪个派生类。我还有一个ProductMapper
类,它带有派生类HatMapper
和ShirtMapper
,所有这些都实现了一堆查找器方法,这些方法让我可以尝试检索某些帽子和衬衫。
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;
};
在我将实例化这些映射器并检索产品的应用程序的逻辑部分中,我遇到了麻烦。我可以毫无问题地实例化 aHatMapper
并拉回对象,与 a和对象相同。这些模式在这些情况下工作得很好(特别是我使用类表继承,即一个带有产品数据的产品表,一个带有帽子特定数据的帽子表,以及一个带有衬衫特定数据的衬衫表)。Hat
ShirtMapper
Shirt
我的问题是,如果我想取回所有产品,包括帽子和衬衫,我该怎么办?我可以实例化 aProductMapper
并获取所有产品数据,但这似乎是错误的方法,因为我必须循环遍历所有Products
我检索和构建的数据,Hats
并Shirts
根据它们在我的程序逻辑部分中的类型。此外,当我添加新产品类型时,我必须修改任何以这种方式处理这种情况的代码。似乎很糟糕。
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.
}
这将引入循环依赖。此外,假设我以某种方式消除了循环依赖关系,则HatMapper
和ShirtMapper
类的结果是Hat
对象和Shirt
对象。因此,当我从 中返回时ProductMapper
,我会感到沮丧,所以我不得不再次在我的逻辑中操作结果,这再次引入了在我引入新产品类型时修改代码的问题。
我不知道该怎么办。在一个完美的世界里,我想要一个Product
类和一个ProductMapper
类,我可以快速扩展这两个类,引入新的产品类型而无需修改现有代码(至少太多)。
我希望能够使用 PoEAA 中的这些模式,它们看起来确实不错且有用,但我不确定这是否只是我无法在 C++ 中做的事情,或者我错过了一些阻止我做的事情。替代模式和方法也非常受欢迎。