什么是暴露类拥有的资源的正确方法? [英] What is the right way to expose resources owned by a class?

查看:138
本文介绍了什么是暴露类拥有的资源的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个有 Document 类的库。 文档的实例可以拥有 Field 的多个实例。 字段有多个子类(例如 IntegerField StringField ) ,甚至API用户可以对其进行子类化并将子类实例提供给 Document (假设用户可以开发自定义类型的数据以存储在字段中)。



我想展示文档所拥有的 Field c>通过API,用户可以与他们进行交互,但不转移所有权



什么是正确的方式




  • 显示 const std :: unique_ptr< Field>& reference - 这感觉很丑陋

  • 暴露一个简单的 Field * pointer - 这不正确,因为用户可能不确定他是否应该删除实例

  • 使用 std :: shared_ptr

    例如,

      class Document {
    private:
    std :: map< std :: string,std :: unique_ptr< Field> >字段;
    // ...
    public:
    // ...

    //这样做是否正确?
    const std :: unique_ptr< Field> & field(const std :: string& name){
    return fields [name];
    }
    }

    我期待您的建议。 >
    (我也欢迎关于@Fulvio建议的替代方法的建议。)

    解决方案

    技术立场,我想指出一个不同的方法,并修改您的设计。这样做的目的是尝试尊重 Demeter法则,并且不授予访问对象的子组件。这是一个有点更难做,没有一个具体的例子,我不能提供许多细节,但试图想象一个类Book由页面组成。如果我想打印一本,两页或更多页的书,用你现在的设计,我可以做:

      auto range = ...; 
    for(auto p:book.pages(range))
    {
    p-> print();
    }

    ,同时遵守Demeter的规定,您将有

      auto range = ...; 
    book.print(/ *可能是这里的范围* /);

    这是倾向于更好的封装,因为你不依赖于书类的内部细节,如果其内部结构更改,您不需要对您的客户端代码执行任何操作。


    Let's say I have a library which has a Document class. An instance of Document can own several instances of Field. Field has multiple subclasses (for example IntegerField and StringField), and even the API user can subclass it and supply subclass instances to Document (let's say the user is allowed to develop a custom type of data to store in a field).

    I'd like to expose the Field instances owned by Document through an API in such a way that users can interact with them, but without transferring ownership.

    What is the right way to do this?

    I thought about:

    • Exposing a const std::unique_ptr<Field>& reference - this feels quite ugly
    • Exposing a plain Field* pointer - this doesn't feel right because the user might be unsure whether he should delete the instance or not
    • Using std::shared_ptr instead - this feels bad because the ownership is not really shared

    For example,

    class Document {
    private:
        std::map<std::string, std::unique_ptr<Field> > fields;
        // ...
    public:
        // ...
    
        // How is this done properly?
        const std::unique_ptr<Field> &field(const std::string &name) {
            return fields[name];
        }
    }
    

    I'm looking forward to your suggestions.
    (I also welcome advice about alternative approaches like what @Fulvio suggested.)

    解决方案

    As others have answered from a technical standpoint, I'd like to point you at a different approach and revise your design. The idea is to try to respect the Law of Demeter and don't grant access to object's sub-components. It's a bit harder to do, and without a specific example I can't provide many details but try to imagine a class Book formed of Pages. If I want to print one, two or more pages of the book, with your current design I can do:

    auto range = ...;
    for( auto p : book.pages(range) )
      {
      p->print();
      }
    

    while abiding by Demeter's you'll have

    auto range = ...;
    book.print( /* possibly a range here */ );
    

    this is slanted towards better encapsulation as you don't rely upon internal details of the book class and if its internal structure changes, you don't need to do anything to your client code.

    这篇关于什么是暴露类拥有的资源的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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