【问题标题】:Should I allow object to delete itself from its interface? Is it correct for OOD?我应该允许对象从其界面中删除自己吗? OOD 是否正确?
【发布时间】:2011-08-16 10:20:44
【问题描述】:

我有以下几点:

interface File
{ 
  String name();
  ...
}

interface FileService
{
  List<File> getAllFiles();
  ...
}

在使用此类接口时如果我决定删除由 File 实例表示的实体(我的意思是从远程服务器中删除),我应该怎么做?

我是否应该为文件接口引入delete() 方法(因为它是信息专家并且可能知道如何从服务器中删除自己)?或者我应该通过void deleteFile(File file) 接口方法将此功能委托给它的创建者——FileService?为什么?

如果第一种情况更合适,如何使对象无效以避免其后续使用?

以及相关:我应该如何处理uploadFile() 案例?谁应该为此负责?因为看起来 FileService 可能会违反 SRP。

谢谢,

【问题讨论】:

  • 视情况而定。如果不深入了解您的软件架构,就不可能对此发表任何明智的看法。
  • 什么是“信息专家”?
  • @Matti VirkkunenInformation_Expert - 我允许自己更正问题
  • @Tomasz Nurkiewicz:是的,我指的是 GRASP 的信息专家,谢谢您的指正。
  • @Oli Charlesworth:取决于什么? FileService 是一个外观,它提供对存储在某处(例如远程服务器上)的文件的访问。它将提供如下方法:uploadFile()findFile(criteria) 等。File i-face 表示远程数据。因此常见的用例:是操作远程文件,获取有关它们的统计信息。

标签: java architecture object ooad


【解决方案1】:

在我看来,这应该是 FileService 的责任。原因和假设是

假设 - 任何文件类型的对象都代表从某处检索的文件。对消费者来说无所谓。我相信 Fileservice 实现是对文件对象执行 CRUD 操作的实现。我也相信 Fileservice 更多的是文件管理问题。因此删除应该在文件服务上。 如果 File 对象中存在删除操作,那么我相信与文件相关的操作没有凝聚力并且分散在各个类中。那是我的意见。我很想听听其他的意见!顺便说一句,文件类在java中是静态的吗?

【讨论】:

    【解决方案2】:

    我认为应该在File

    如果您只有一个作为文件工厂的 FileService(每个连接到服务器),您可能希望该服务保持最新。然后你可以使用一些东西:

    FactoryServiceImpl implements FactoryService {
    
        public File findFile(criteria) {
            return new FileImpl(this);
        }
    }
    
    // This should be package scope!
    FileImpl implements File {
      private FactoryService service;
    
      // package scope!
      FileImpl(FactoryService service) {
          this.service = service;
      }
    
      public delete() {
          // invalidate this object - all calls should throw exception
    
          // Inform the service that this File should be deleted from
          // the server; or if the FileImpl does that itself, that the
          // FileService should update the cache of available files
          service.delete(this);
      }
    }
    

    编辑

    现在有一个循环依赖,这不是很好。 JVM 可能可以检测到它并清理任何东西,但您也可以使用 Wea​​kReference。

    无论您是使用精简的工厂和事实文件,还是相反,这都是一种设计选择。但是他们需要能够通信,因为通过工厂删除的文件应该知道它已被删除。

    一些代码(假设事实工厂):

    // This should be package scope!
    FileImpl implements File {
      private Weakreference<FactoryService> serviceRef;
    
      // package scope!
      FileImpl(FactoryService service) {
          this.serviceRef = new WeakReference<FactoryService>(service);
      }
    
      public delete() {
          // invalidate this object - all calls should throw exception
    
          // Inform the service that this File should be deleted from
          // the server; or if the FileImpl does that itself, that the
          // FileService should update the cache of available files
    
          FactoryService service = serviceRef.get();
          if (service != null) {
              service.delete(this);
          }
      }
    }
    

    在这种情况下,我假设一个事实工厂,因为可能涉及网络连接,并且在多个对象和线程之间共享连接往往会使关闭该连接的责任变得不清楚。

    因此,FactoryService 接口应该有一个方法 close()dispose() 来终止连接并使所有文件无效(因为它们不再可访问)。

    编辑 2

    就 OOD 而言,我可能会尽量模仿 java File API。因此,可以告诉对象删除自己。实现是在 File 中还是在 FileSystem 中的某个地方并不重要(对于接口和类的用户)。

    【讨论】:

    • 但是这样我们得到了一个循环依赖,不是吗?我的意思是File 取决于它的创建者,我们遇到了低耦合。我最好像这样实现:public FileImpl(Connection connection)... void delete() { Connection.sendRequest(...) }。但问题是我不知道谁真正应该负责文件删除。
    • @baranov.dmi 更新了答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-22
    • 2015-10-04
    • 2021-01-26
    • 1970-01-01
    • 2011-07-14
    相关资源
    最近更新 更多