Я рефакторинг кучу старого кода. Моя основная задача - отделить поведение от базы данных. Текущая реализация напрямую обращается к базе данных, что затрудняет тестирование и делает такие вещи, как реализация слоев кэширования и т. Д. До этого момента я с большим успехом использовал комбинацию инверсии зависимостей и читателей / писателей, то есть достиг некоторых из наших более сложных типов.
У меня есть абстрактный базовый пользовательский класс, который инкапсулирует информацию, общую для всех наших пользовательских типов. Наследование от базового класса - это ряд специализаций базового пользовательского типа, каждая из которых содержит информацию, специфичную для этого типа.
Если у меня есть указатель или ссылка на базовый класс, и мне нужно сохранить этого пользователя в базе данных, как мне узнать, какой писатель использовать? Если бы я использовал писателя для базового класса, информация, специфичная для производных классов, была бы потеряна. Помещение абстрактного метода getUserType () в базовый класс, который затем должен быть реализован каждым производным, кажется чем-то вроде хака. Это может быть случай двойной отправки, но детали реализации для меня немного неясны.
class User
{
public:
std::string
name() const
{
return m_name;
}
void
name(const std::string& name)
{
m_name = name;
}
private:
std::string m_name;
}
class EmailUser : User
{
public:
std::list<std::string>
emails() const
{
return m_emails;
}
void
emails(const std::string<std::string>& emails)
{
m_emails = emails;
}
private:
std::set<std::string> m_emails;
}
class UserWriter
{
public:
virtual void
write(User& user) = 0;
}
class DBUserWriter : UserWriter
{
public:
void
write(User& user)
{
SQLExecute("SOME SQL UPDATE STMT %s", user.name());
}
}
class DBEmailUserWriter : UserWriter
{
public:
void
write(User& user)
{
m_baseUserWriter.write(user);
SQLExecute("SOME SQL UPDATE STMT %s", user.email.front());
}
private:
DBUserWriter m_baseUserWriter;
}