gpt4 book ai didi

c++ - "Modern C++ Design"DocumentManager 设计是否正确?

转载 作者:行者123 更新时间:2023-11-28 06:23:00 25 4
gpt4 key购买 nike

我在翻《Modern C++ Design》这本书,看到《8.1 对象工厂的必要性》中解释了下面的代码,我有些疑惑。

  1. 我的理解是,每次编写派生文档类时,“CreateDocument()”都应该在新的派生文档管理器类中被覆盖吗?
  2. 如果是,那么将有太多派生的 documentManagers 并且需要其自己的工厂方法!!!
  3. 如果否,则“CreateDocument()”应该采用一个 ID,以便它可以准确地决定在一个对象中创建什么。但这也意味着,每次创建 derivedDocument 时,他还应该找到正确的 documentManager 并更新 CreateDocument() 方法。但是我们必须决定是否拥有 documentManagers 工厂,因为它们可能很少也可能很多。

    我的主要疑问是这是否是一个解决方案,或者我是否忽略了重点。根据该书,CreateDocument() 是 GoF 书中的工厂方法。 “CreateDocument()”基于 ID 和许多条件创建新的派生文档至少是有意义的。但是很多derivedDocumentManager没有意义。

书上的

DocumentManager

class DocumentManager
{
...
public:
Document* NewDocument();
private:
virtual Document* CreateDocument() = 0;
std::list<Document*> listOfDocs_;
};

Document* DocumentManager::NewDocument()
{
Document* pDoc = CreateDocument();
listOfDocs_.push_back(pDoc);
...
return pDoc;
}

客户端代码:

Document* GraphicDocumentManager::CreateDocument()
{
return new GraphicDocument;
}

最佳答案

更新:您的问题已经过大量编辑,以提供不同的关注点。还有几点:

  • 您似乎在想,任何提到“工厂”的地方都必然涉及一个具体函数,该函数接受一些输入并根据输入吐出许多可能的动态类型之一的实例。这只是一种类型的工厂,而不是您的代码中出现的类型。

阅读有关 Factory Method Pattern 的信息希望你会意识到这就是你所拥有的。它可以让您执行以下操作:

std::string compress(DocumentManager& d, const std::string& uncompressed)
{
std::unique_ptr<Document> doc = std::make_unique(d.NewDcoument());
doc = uncompressed; // interpret to form document of whatever type
return zlib::compress(d.data(), d.size()); // compress as binary blob
}

在这里,一个 compress()可以使用一些原始输入调用函数,并尝试首先创建一个正确的调用者指定类型的文档,然后将一些数据填充到其中并压缩它....

工厂方面是压缩在不知道所涉及的具体类型的情况下创建对象的能力,因为 - 没有模板化并且没有任何切换 - 它无法在许多构造函数之间进行选择。


根据原始问题回答...

Are we not moving the problem of object creation from Document to DocumentManager class. I mean we have to create [concrete] DocumentManager?

这就是重点,不是吗 - 围绕创建特定类型的 list<Document*> 进行额外的记录保存(在本例中为 Document)

如果我们让客户端代码创建Document s 直接,拥有这样的列表将取决于客户端每次创建对象时更新列表(或需要对 Document 构造函数进行侵入性更改)。如果我们想说在对象创建时添加时间戳,我们必须修改客户端代码中创建任何类型的 Document 的每个地方。 .

如果我们没有 DocumentManager基类,我们必须将类似的逻辑和数据成员放入任意数量的 GraphicDocumentManager 中, TextDocumentManager , AudioDocumentManager等,并且无法以多态方式处理这些管理器(例如创建 vector<DocumentManager*> ,编写函数 ala void f(DocumentManager&);

How to keep track of all the derived classes of DocumentManager, created by many independent clients?

设计中没有任何内容旨在这样做,并且 C++ 没有让您枚举派生类型的内省(introspection)工具——无论是在编译时还是在程序开始运行时。但是,如果您准备等待 NewDocument要被调用,您可以记录具体的地址 DocumentManager -派生对象和/或访问它们的 RTTI 信息(例如,这将让您计算已创建的不同类型的文档,或尝试显示实现定义的(可能为空)name() 动态类型的字段... .

Should not the listOfDocs_ be static and DocumentManager be a singleton.

可能不会。该程序可能想要做一些类似保留 DocumentManager 的事情。每个 TCP 客户端、每个文件系统、每个用户等的对象 - 那么为什么不自然地限制它?使一个更灵活的DocumentManager变得容易和更好类型,然后让客户端代码应用单例包装器(例如函数返回一个 static 实例),如果这对它们确实有用的话。这也使测试更容易:您可以自由创建 DocumentManager s,运行测试,让析构函数运行,创建另一个等等......

My main doubt is, is that a solution at all or I am missing some point.

似乎您遗漏了一些“位图”,但没有手头的书或您提出的更一般的问题/理解陈述,很难知道它可能是什么。

According to the book "CreateDocument()" is the GoF book's factory method. But I am not able to understand the above points.

是的 - 这是一个工厂方法,因为它创建许多不同动态类型的对象中的任何一个,但返回一个指向基类的指针,通过该指针可以多态地处理它们。

关于c++ - "Modern C++ Design"DocumentManager 设计是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29028246/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com