- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在通读 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;
};
在我要实例化这些映射器并检索产品的应用程序的逻辑部分,我遇到了麻烦。我可以实例化一个 HatMapper
并毫无问题地拉回 Hat
对象,与 ShirtMapper
和 Shirt
对象一样。这些模式在这些情况下效果很好(特别是我使用类表继承,即一个包含产品数据的产品表,一个包含帽子特定数据的帽子表,以及一个包含衬衫特定数据的衬衫表)。
我的问题是,如果我想检索所有产品,包括帽子和衬衫,我该怎么办?我可以实例化一个 ProductMapper
并获取所有产品数据,但这似乎是错误的方法,因为我必须循环遍历我检索和构建的所有 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++ 中做的事情,或者我遗漏了一些阻止我使用的东西正在做。替代模式和方法也非常受欢迎。
最佳答案
感觉就像Type Object pattern在这种情况下可能会有所帮助,我知道链接是关于游戏编程的,但足以将该模式应用于其他领域。
现在的问题是,如果您想添加产品,您必须添加几个类,正如您所注意到的那样,这些类可能变得难以维护。
编辑:也许您可以使用类似的东西(代码是 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
};
关于c++ - 在 C++ 中使用映射器处理派生类创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25030800/
我有一个无法理解的奇怪编译问题。 //I know, you should never derive from the STL Library template class SharedClass :
我是一个刚开始学习 Haskell 的菜鸟,所以如果我问愚蠢的问题,请耐心等待。 最近我在 SO 中遇到了演示如何导出函数和表达式的类型和实现的问题(诸如 How can I understand "
如何自动派生此 GADT 的 Read 实例: {-# LANGUAGE GADTs, StandaloneDeriving #-} data TypeDec a where TypeDecInt
我遇到了我想要的情况 Deal class要注意它DealDetail type反之亦然,我想 DealDetail注意Deal type .将来我想有很多 Deal 的后代和 DealDetails
我是 C# 新手,所以请多多包涵。 好的,所以我在不同的程序集中有两个类需要相互引用: namespace AssemblyA { class A { private B MyB {
简而言之,我已经实现了一个派生自 SynchronizationContext 的类,以便 GUI 应用程序可以轻松地使用在 GUI 线程以外的线程上引发的事件。我非常感谢对我的实现的评论。具体来说,
我正在设计一个小型系统,想知道如何为派生类分配内存的细微差别。 如果我有两个类(class) class foo { public: int a; Foo(): a(0) {}; }; class
我正在尝试编写一个派生 PartialEq 的枚举,其中包含一个手动执行此操作的特征对象。我使用了解决方案 here为了强制 Trait 的实现者编写相等方法。这无法编译: trait Trait {
以下代码可以编译(特别是 MyError 被识别为具有调试特性): use std::str; use std::fmt; #[derive(Debug)] enum MyError where F:
是否有一种简单的方法来注释结构中的字段,以便在派生 PartialEq 特征时忽略它们?例如: #[derive(PartialEq,Eq)] pub struct UndirectedGraph {
我正在编写代码来处理“Foo”类型的对象。 foo 是一种容器,为了提供对其元素的高效和抽象访问,它提供了 Element 类型的嵌套类。 Element 包装对象在容器中的位置。 现在,“Foo”可
假设如下: class child : public parent { public: fun1(parent * obj); //somewhere on the child class
我有几个模板类 template class Transition { public: virtual Cost getCost() = 0; }; template class St
我正在尝试使用自定义 QSortFilterProxyModel . 这是我的标题: #include class QSortFilterProxyModel_NumbersLast : publi
我正在使用 C# 和 mvc3。我在解决方案中添加了一个项目。我想创建一个新 Controller 并让它从我添加的项目中的 Controller 派生。我该怎么做? 最佳答案 在 Visual St
我在 python 中有一个对象,它派生自 QtGui.QGraphicsPixmapItem,具有一些基本属性和方法。在对此对象的引用上调用 deepcopy 后,当我尝试使用该副本时收到一条错误消
由于只能给FixedDocument添加页面,所以我写了一个派生类: public class CustomFixedDocument : FixedDocument { public voi
我在自定义 QMainWindow 时遇到了很大的问题,因为我不知道如何实现以下内容: 在 QMainWindow 文档中,QMainWindow 有一些用于工具栏、停靠小部件、状态栏和其他的特殊区域
我想感受一下QT,决定写一个小的十六进制编辑器。为此,我需要一个允许滚动的小部件。经过一番研究,我发现 QTextEdit 为此目的派生自 QAbstractScrollArea。在阅读 QAbstr
我正在寻找一种可以从已经发生的洗牌过程中派生出 key 的算法。 假设我们有被打乱的字符串“Hello”: "hello" -> "loelh" 现在我想从中导出一个 key k,我可以用它来撤销洗牌
我是一名优秀的程序员,十分优秀!