应该将“下载”功能封装在对象或其他地方吗?

时间:2011-11-29 15:58:55

标签: java oop

我有一个Dog个对象,每个Dog都有一个colour和一个photoUrl,这是它的照片在互联网上的位置。

class Dog {
     private String colour;
     private String photoUrl;
     private Bitmap photo;

     public Dog(String colour, String photoUrl){
         this.colour = colour;
         this.photoUrl = photoUrl;
     }
}

我想下载照片并将其存储在磁盘上。我应该在Dog.download()或其他地方实现下载功能,比如在一个名为FileDownloader的新类中?这个问题有设计模式吗?

6 个答案:

答案 0 :(得分:6)

下载文件是一个跨领域的问题,与狗没有特别的关系。因此,我建议您在Dog之外存在一个DownloadUtil(或类似的东西),您可以在其中实现下载。

答案 1 :(得分:2)

我同意也许狗不是最适合它的地方。也许如果你有其他可下载的对象或计划,你可以做...

  public interface Downloadable { public String getUrl(); }

  public class Dog implements Downloadable...

  public class Downloader { public Bitmap download(Downloadable obj); }

答案 2 :(得分:2)

目前为止好几个答案。但是,我有一些意见:

  1. 我不认为下载文件是一个贯穿各领域的问题。安全,日志记录等
  2. “可下载”是一个糟糕的抽象。更好的东西可能是“资源”或类似的东西(比如Spring)。
  3. 扩展抽象超类在这个类中不是一个好主意。我不认为狗是“可下载的”或类似的。
  4. 使用“setDownloader(Downloader downloader)”之类的东西会使你的类变得可变。除非你需要这样的行为,否则我建议让它变成不可变的。
  5. 所以,可能一个好主意是复制一些关于此的春天概念。请参阅:http://static.springsource.org/spring/docs/3.0.6.RELEASE/spring-framework-reference/html/resources.html

    class Dog {
        private final String color;
        private final Photo photo;
    
        public Dog(final String color, final Photo photo) {
            this.color = color;
            this.photo = photo;
        }
    }
    
    class Photo {
    
        private final Resource resource;
    
        public Photo(final String path) throws MalformedURLException {
            this.resource = new UrlResource(path);
        }
    
        public String getUrl() {
            return resource.getUrl();
        }
    
        public Bitmap getBitmap() {
            final InputStream is = resource.getInputStream();
            // transform is to Bitmap
            // cache the result
            return bitmap;
        }
    
    }
    
    class UrlResource implements Resource {
        private final URL url;
    
        public UrlResource(final String path) throws MalformedURLException {
            Assert.notNull(path, "Path must not be null");
            this.url = new URL(path);
        }
    
        @Override
        public InputStream getInputStream() throws IOException {
            final URLConnection con = this.url.openConnection();
            con.setUseCaches(false);
            try {
                return con.getInputStream();
            } catch (final IOException ex) {
                // Close the HTTP connection (if applicable).
                if (con instanceof HttpURLConnection) {
                    ((HttpURLConnection) con).disconnect();
                }
                throw ex;
            }
        }
    
        @Override
        public String getUrl() {
            return url.toString();
        }
    }
    
    interface Resource {
        InputStream getInputStream() throws IOException;
    
        String getUrl();
    }
    
    
    // Multi thread approach.... just the idea... it won't compile
    interface AsyncResource extends Resource {
        Future<Data> getData();       
    }
    
    // On Photo
    public Photo(final AsyncResource resource) {
        this.resource = resource;
    }
    
    public Bitmap getBitmap() {
        final Future<Data> data = resource.getData();
         // call data.get(), Hopefully won't block
        // transform is to Bitmap
        // cache the result
        return bitmap;
    }
    
    class AsyncResourceProvider {
      final ExecutorService threadExecutor = Executors.newFixedThreadPool(10);
    
      AsyncResource schedule(String path) {
        // submit the taks and return the future
      }
    
    }
    // Create a Dog and a Photo
    AsyncResource resource = asyncResourceProvider.schedule(path);
    Dog d = new Doc("black", new Photo(resource));
    

答案 3 :(得分:1)

我看到两个选项:

a)如果层次结构允许,则创建具有该功能的抽象超类。这很容易,但很僵硬。

b)更灵活的方法是在Downloader界面中委派它。每个对象都将在外部提供(setDownloader(Downloader downloader))。也许允许在对象中自动创建的默认HttpDownloader。更灵活,更轻松的测试,但还有一些工作。

最后,您应该评估您的问题并确定额外的工作是否值得将来需要该功能的风险。

答案 4 :(得分:1)

创建另一个类Downloader,在其构造函数中使用一个接口Animal。然后它也适用于猫...

答案 5 :(得分:1)

拥有Dog.download()。但是让Dog.download()转而调用一个fileDownloader.download(),就像Chris指出的那样。

我不确定你是否可以将其称为设计模式,但这种做法称为delegation

<小时/>

更新

并且不要将Dog对象传递给fileDownloader.download(),而只传递它应该关注的URL。除了下载逻辑更改之外,fileDownloader不需要因任何原因而更改。另请参阅Single Responsibility principle