如何在这种情况下保持良好的数据封装? [英] How can I maintain a good data encapsulation in this situation?

查看:123
本文介绍了如何在这种情况下保持良好的数据封装?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



在这个例子中,客户端在商店中购买了很多东西,而这个商店有关于这个客户买的东西的信息。我叫它库存



商店,打印报告为每个客户端。在下面的代码中,main只有一个Inventory,只是为了样例。



问题是:当我打印报表时,客户端,但不丢失封装。我的意思是,我想没有类可以修改库存的内容。



我想做的是将地图转换为一个矢量(我需要一些东西排序数据)并传递此向量(dinamically allocated)。
我在类 Inventory 分配此向量,但谁删除
是类 Report ,这不是正确的方式做事情,但我不知道如何传递这些信息,而不这样做。



无论如何,报表类可以获得指向一本书,并使用其 set 函数或指向其他书。



有人可以给我一个提示,我在这种情况下要做什么?



感谢。



对不起长码。



主要:

  int main(void)
{
Inventory i;
报告r(i);

i.addBook(Foo Bar I);
i.addBook(Foo Bar II);

r.generateReport();

return 0;
}

以.h为类别的报表:

  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();
}

.h中的类别库存:

  class Inventory 
{
private:
map< int,Book *>图书;

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名称)));
}

向量< pair< int,Book *>> * Inventory :: getBooks()
{
return new vector< pair< int,Book *>>(books.begin(),books.end());
}


解决方案

映射转换为向量只引入一个附加的依赖:报告必须知道库存的内部。



我宁愿推荐使用 vistitor design pattern :目标是从您探索的数据结构(库存及其项目)中分离算法(生成报告,访问者)。

  class Item {...}; //对象结构
class Book:public Item {...};
class Inventory {...};

class Visitor {...}; //应该在结构上执行的算法
class Report:public Visitor {...};

这也可以简化您的库存的实施,因为您不再需要预见不同的容器对于不同类型的项(如果他们都继承一些常见的元素基类)。



Theres在这种模式上充满了烦恼。我建议你来自Gamma& amp;公司的设计模式,可重用面向对象软件的元素 al:它的原始教科书,并猜测什么,演示代码显示与定价访问者的库存;-)



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


I am new in c++, I am trying to make a very simple CRUD program.

In this example, a client bought many things in a store, and this store has the information about the things that this client bought. I called it Inventory.

The store, wants to print a Report for every client. In the code below, the main just has one Inventory, just for sample.

The problem is: When I want to print the Report, I have to get the data from the client, but without lose encapsulation. I mean, I want that no class can modify the content of the inventory.

What I am trying to do is convert the map into a vector (I need something to sort the data) and pass this vector (dinamically allocated). I am allocating this vector at the class Inventory but who is deleting is the class Report, this is not the correctly way to do things, but I do not know how to pass this information without doing like this.

Anyway, the report class can get the pointer to a Book, and use its set function or point to other Book. Again, I do not know how to do it correctly.

Can someone give me a tip what I have to do in this case ?

Thanks.

Sorry for the long code.

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 in .h:

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

Class Report in 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 in .h:

class Inventory 
{
private:
    map<int, Book *> books;

public:
    void addBook(int code, const string& name);
    vector<pair<int, Book *>> * getBooks();
};

Class Inventory in .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());
}

解决方案

With your approach, the trick to transform the map into a vector introductes only an additional dependency: the report has to know about the internals of the inventory.

I'd rather recommend to go the way of the vistitor design pattern: the goal is to separate the algorithm (producing the report, the visitor) from the datastructure you explore (the inventory and its items).

class Item { ...};      // Your object structure 
class Book : public Item { ... }; 
class Inventory { ...}; 

class Visitor { ... };  // Algorithms that shall be executed on structure
class Report : public Visitor {...};

This could also simplify the implementation of your inventory, as you'd no longer need to foresee different containers for different kind of items (provided they all inherit from some common element base class).

Theres is plenty of litterature on this pattern. I recommend you Design patterns, elements of reusable object oriented software from Gamma & al: its the orginal textbook, and guess what, the demo code shows an inventory with a pricing visitor ;-)

Here a naive on-line example based on your problem, to illustrate how it could work.

这篇关于如何在这种情况下保持良好的数据封装?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆