oop — обработка создания производного класса с помощью картографов в переполнении стека

Я сейчас читаю 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 основываясь на их типе в моей логической части программы. Кроме того, мне придется изменить любой код, который обрабатывает ситуацию таким образом, когда я добавляю новые типы продуктов. Кажется плохим

В книге Фаулера есть примеры картографов с базовым картографом, использующих производные картографы, что мне кажется совершенно неправильным (приходится модифицировать базовый картограф каждый раз, когда я добавляю новый продукт, не очень хорошо). Вот быстрый пример того, как это делается там:

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 ++, или мне не хватает того, что мешает мне это делать. Альтернативные модели и подходы также действительно приветствуются.

1

Решение

Это похоже на Тип объекта может помочь в этом случае, я знаю, что ссылка о программировании игры, но достаточно применить шаблон к другим доменам.

Проблема сейчас в том, что если вы хотите добавить продукты, вам нужно добавить несколько классов, которые, как вы заметили, могут быть сложными в обслуживании.

Редактировать: Может быть, вы могли бы использовать что-то подобное (код 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
};
0

Другие решения


По вопросам рекламы [email protected]