在这种情况下,我如何才能保持良好的数据封装

How can I maintain a good data encapsulation in this situation?

本文关键字:数据封装 这种情况下      更新时间:2023-10-16

我是c++的新手,我正在尝试制作一个非常简单的CRUD程序。

在这个例子中,一个客户在商店里买了很多东西,这个商店有这个客户买的东西的信息。我称之为Inventory

商店希望为每个客户打印一个Report。在下面的代码中,main只有一个Inventory,仅用于示例。

问题是:当我想打印报告时,我必须从客户端获取数据,但不能丢失封装。我的意思是,我希望任何类都不能修改清单的内容。

我想做的是将地图转换为向量(我需要一些东西来对数据进行排序),并传递这个向量(按常规分配)。我在类Inventory中分配这个向量,但谁在删除是类Report,这不是正确的做法,但如果不这样做,我不知道如何传递这些信息。

无论如何,报表类可以获得指向Book的指针,并使用其set函数或指向其他Book。再说一遍,我不知道如何正确地做。

有人能给我一个提示吗?在这种情况下我该怎么办?

谢谢。

抱歉代码太长。

Main:

int main(void)
{
    Inventory i;
    Report r(i);
    i.addBook("Foo Bar I");
    i.addBook("Foo Bar II");
    r.generateReport();
    return 0;
}

课堂报告单位:小时:

class Report
{
private:
    Inventory* i;
public:
    Report(Inventory& i);
    void generateReport();
};

cpp:中的类报告

Report::Report(Inventory& i)
{
    this->i = &i;
}
void Report::generateReport()
{
    ofstream out ("Report.txt");
    out << "Books: " << endl;
    vector<pair<int, Book *>> * b = i->getBooks();
    for(pair<int, Book *> p : *b)
    {
        out << p.first << ": " << p.second.getName() << endl;
    }
    out << endl;
    delete b;
    out.close();
}

分类库存单位:

class Inventory 
{
private:
    map<int, Book *> books;
public:
    void addBook(int code, const string& name);
    vector<pair<int, Book *>> * getBooks();
};

.cpp中的类清单:

void Inventory::addBook(int code, const string& name)
{
    books.insert(pair<int, Book *>(code, new Book(name)));
}
vector<pair<int, Book *>> * Inventory::getBooks()
{
    return new vector<pair<int, Book *>>(books.begin(), books.end());
}

您的库存类应该有这个接口:

class Inventory 
{
private:
    map<int, Book *> books;
public:
    using const_iterator = std::map<int, Book*>::const_iterator;
    void addBook(int code, const string& name);
    const_iterator begin() const { return books.begin(); }
    const_iterator end() const { return books.end(); }
};

没有理由将地图副本创建为矢量!这是低效的,没有理由这么做。

重写generateReport以使用此接口,如下所示:

for(const auto &p : *i)
{
    out << p.first << ": " << p.second.getName() << endl;
}
out << endl;

使用您的方法,将map转换为vector的技巧只引入了一个额外的依赖项:报告必须了解库存的内部。

我建议采用visitor设计模式:目标是将算法(生成报告、访问者)与您探索的数据结构(库存及其项目)分离。

class Item { ...};      // Your object structure 
class Book : public Item { ... }; 
class Inventory { ...}; 
class Visitor { ... };  // Algorithms that shall be executed on structure
class Report : public Visitor {...};

这也可以简化清单的实现,因为您不再需要为不同类型的项预见不同的容器(前提是它们都继承自某个公共元素基类)。

这个图案上有很多乱丢的东西。我推荐您设计模式,可重用的面向对象软件的元素来自Gamma&al:这是最初的教科书,你猜怎么着,演示代码显示了一个带有定价访问者的库存;-)

这里有一个基于你的问题的天真的在线例子,来说明它是如何工作的。