Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 读写器和派生类的解耦持久性_C++_Design Patterns - Fatal编程技术网

C++ 读写器和派生类的解耦持久性

C++ 读写器和派生类的解耦持久性,c++,design-patterns,C++,Design Patterns,我正在重构一堆旧代码。我的主要目标是将行为与数据库分离。当前的实现直接访问数据库,这使得测试和执行诸如实现缓存层等操作变得困难。。。到目前为止,我一直在使用依赖项倒置和读写器的组合,并取得了巨大成功,也就是说,直到我找到了一些更复杂的类型 我有一个抽象的基本用户类,它封装了所有用户类型所共有的信息。从基类继承是基类用户类型的许多专门化,每个专门化封装了特定于该类型的信息 如果我有一个指向基类的指针或引用,并且我需要将该用户持久化到数据库,那么我如何知道要使用哪个编写器?如果将writer用于基类

我正在重构一堆旧代码。我的主要目标是将行为与数据库分离。当前的实现直接访问数据库,这使得测试和执行诸如实现缓存层等操作变得困难。。。到目前为止,我一直在使用依赖项倒置和读写器的组合,并取得了巨大成功,也就是说,直到我找到了一些更复杂的类型

我有一个抽象的基本用户类,它封装了所有用户类型所共有的信息。从基类继承是基类用户类型的许多专门化,每个专门化封装了特定于该类型的信息

如果我有一个指向基类的指针或引用,并且我需要将该用户持久化到数据库,那么我如何知道要使用哪个编写器?如果将writer用于基类,则特定于派生类的信息将丢失。在基类上放置一个抽象的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;
}
类用户
{
公众:
字符串
name()常量
{
返回m_名称;
}
无效的
名称(常量标准::字符串和名称)
{
m_name=名称;
}
私人:
std::字符串m_名称;
}
类EmailUser:用户
{
公众:
标准::列表
电子邮件()常量
{
返回m_电子邮件;
}
无效的
电子邮件(const std::string和电子邮件)
{
m_电子邮件=电子邮件;
}
私人:
std::设置m_电子邮件;
}
类用户编写器
{
公众:
虚空
写入(用户和用户)=0;
}
类DBUserWriter:UserWriter
{
公众:
无效的
写入(用户和用户)
{
SQLExecute(“某些SQL更新STMT%s”,user.name());
}
}
类DBEmailUserWriter:UserWriter
{
公众:
无效的
写入(用户和用户)
{
m_baseUserWriter.write(用户);
SQLExecute(“某些SQL更新STMT%s”,user.email.front());
}
私人:
DBUserWriter m_baseUserWriter;
}

以下是使用wikipedia页面中指定的双重分派实现的示例:

#include <iostream>
using namespace std;

class Writer;

class User
{
public:
    std::string name() const { return m_name; }
    void name(const std::string& name) { m_name = name; }
    virtual void accept(Writer & writer) const;

private:
    std::string m_name;
};

class EmailUser : public User
{
public:
    std::string email() const { return m_email; }
    void email(const std::string& email) { m_email = email; }
    virtual void accept(Writer & writer) const;

private:
    std::string m_email;
};

class Writer
{
public:
  void process(const User& user) { user.accept(*this); }
  virtual void write(const User& user) { cout << user.name() << endl; }
  virtual void write(const EmailUser& user) { cout << user.email() << endl; }
};

class SubWriter : public Writer
{
public:
  void process(const User& user) { user.accept(*this); }
  void write(const User& user) { cout << "[" << user.name() << endl; }
  void write(const EmailUser& user) { cout << "[" << user.email() << endl; }
};

void User::accept(Writer & writer) const { writer.write(*this); }
void EmailUser::accept(Writer & writer) const { writer.write(*this); }

int main()
{
  User u;
  EmailUser eu;
  Writer w;
  SubWriter s;

  u.name("Hugo Peixoto");
  eu.email("hugo.peixoto@gmail.com");

  w.process(u);
  w.process(eu);

  s.process(u);
  s.process(eu);

  return 0;
}
#包括
使用名称空间std;
班主任;
类用户
{
公众:
std::string name()常量{return m_name;}
void name(const std::string&name){m_name=name;}
虚拟无效接受(写入方和写入方)常量;
私人:
std::字符串m_名称;
};
类EmailUser:公共用户
{
公众:
std::string email()常量{return m_email;}
无效电子邮件(const std::string&email){m_email=email;}
虚拟无效接受(写入方和写入方)常量;
私人:
std::字符串m_电子邮件;
};
班主任
{
公众:
无效进程(constuser&User){User.accept(*this);}

virtualvoidwrite(constuser&User){cout下面是一个使用wikipedia页面中指定的双分派实现的示例:

#include <iostream>
using namespace std;

class Writer;

class User
{
public:
    std::string name() const { return m_name; }
    void name(const std::string& name) { m_name = name; }
    virtual void accept(Writer & writer) const;

private:
    std::string m_name;
};

class EmailUser : public User
{
public:
    std::string email() const { return m_email; }
    void email(const std::string& email) { m_email = email; }
    virtual void accept(Writer & writer) const;

private:
    std::string m_email;
};

class Writer
{
public:
  void process(const User& user) { user.accept(*this); }
  virtual void write(const User& user) { cout << user.name() << endl; }
  virtual void write(const EmailUser& user) { cout << user.email() << endl; }
};

class SubWriter : public Writer
{
public:
  void process(const User& user) { user.accept(*this); }
  void write(const User& user) { cout << "[" << user.name() << endl; }
  void write(const EmailUser& user) { cout << "[" << user.email() << endl; }
};

void User::accept(Writer & writer) const { writer.write(*this); }
void EmailUser::accept(Writer & writer) const { writer.write(*this); }

int main()
{
  User u;
  EmailUser eu;
  Writer w;
  SubWriter s;

  u.name("Hugo Peixoto");
  eu.email("hugo.peixoto@gmail.com");

  w.process(u);
  w.process(eu);

  s.process(u);
  s.process(eu);

  return 0;
}
#包括
使用名称空间std;
班主任;
类用户
{
公众:
std::string name()常量{return m_name;}
void name(const std::string&name){m_name=name;}
虚拟无效接受(写入方和写入方)常量;
私人:
std::字符串m_名称;
};
类EmailUser:公共用户
{
公众:
std::string email()常量{return m_email;}
无效电子邮件(const std::string&email){m_email=email;}
虚拟无效接受(写入方和写入方)常量;
私人:
std::字符串m_电子邮件;
};
班主任
{
公众:
无效进程(constuser&User){User.accept(*this);}

虚拟无效写入(常量用户和用户){因此,我可以看到您的解决方案的唯一缺点是,它要求我对每个用户类型使用相同的编写器,这使得很难混合和匹配缓存机制或数据存储。您可以有多个编写器。我更新了代码,检查这是否是您要找的。因此,我可以看到您的解决方案的唯一缺点是请允许我对每种用户类型使用相同的编写器,这样很难混合和匹配缓存机制或数据存储。您可以有多个编写器。我已更新了代码,请检查您是否需要这些编写器。