Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重写方法与多次实现方法_Java - Fatal编程技术网

Java 重写方法与多次实现方法

Java 重写方法与多次实现方法,java,Java,假设我有一个从web下载新闻提要的类 public class NewsDownloader { public String downloadNewsFast() { // download a news feed using a wifi connection } public String downloadNewsNormal() { // download a news feed using a 3g connection } pu

假设我有一个从web下载新闻提要的类

public class NewsDownloader {
   public String downloadNewsFast() {
      // download a news feed using a wifi connection
   }

   public String downloadNewsNormal() {
      // download a news feed using a 3g connection
   }

   public String downloadNewsSlow() {
      // download a news feed using a GPRS connection
   }
}
在上述情况下,根据可用的连接,有3种方式下载新闻。如您所见,前面提到的类定义了3个方法(我知道在继承的情况下,重新定义方法适用于静态方法)

如果
NewsDownloader
的客户端根据可用的连接有条件地调用下载方法,如

public class NewsReader {
   NewsDownloader n = new NewsDownloader();

   public void getLatestNews(Connection c) {
      if (c.getType().equals("Wifi")) {
         n.downloadNewsFast();
      }
      else if (c.getType.equals("3g")) {
         n.downloadNewsNormal();
      }
      else {
         n.downloadNewsSlow();
      }
   }
}
我的问题是双重的

  • 我在设计如上所述的
    NewsDownloader
    时会遇到什么问题,而不是使用更抽象的方式,比如使用工厂模式
  • NewsDownloader
    更抽象的设计会给
    新闻阅读器带来什么好处(如果有的话)
  • 我已经阅读了工厂方法和抽象工厂模式的优点,并为自己的利益实现了它们。然而,我看不出上面描述的方法和工厂模式之间有什么区别


    我希望人们不要认为这是一种欺骗!我只是想阐明抽象设计为我正在撰写的一个项目所解决的问题,我不知道你想把事情抽象化的原因是什么。一般规则:

    • 抽象类用于代码重用
    • 接口定义合同
    • 应用控制反转原理,工厂模式有时可以提供帮助
    遵循这些指导原则,我看不到立即考虑为NewsDownloader创建一个抽象类的理由,因为只有其中一个。您可以将其作为一个接口而不是一个类来放松耦合,我认为这就是您所问的好处。最后,新闻阅读器不应该实例化它自己的新闻下载程序,而是依赖于它以某种方式被注入


    更新:在代码中列出这些原则方面做得很好。

    您不一定会遇到问题,但有一种想法是,当新的网络连接被发明时,您需要同时更新新闻阅读器和新闻下载器。如果(例如)您使用了工厂模式,那么您可以这样做,即使用downloadNews()方法返回一个对象,而NewsReader类不需要担心它是否慢、快等等;返回的对象只需要有一个downloadNews()方法,新闻阅读器就会很高兴


    但是你的代码肯定能用,它不是理想的设计。

    你可以创建一个新闻下载程序的界面,并创建三个具体的类,以不同的速度下载。并设置新闻阅读器(NewsDownloader n)的属性以保存具体实现。

    如果您按照以下方式进行重构:

    public interface NewsDowloader
    {
        String download();
    }
    
    public class FastNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class NormalNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class SlowNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class NewsReader 
    {
        public void getLatestNews(NewsDownloader downloader) 
        {
            downloader.download();
        }
    }
    
    然后,新闻阅读器可能看起来像这样:

    public interface NewsDowloader
    {
        String download();
    }
    
    public class FastNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class NormalNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class SlowNewsDownloader
        implements NewsFownloader
    {
        public String download() { /* ... */ }
    }
    
    public class NewsReader 
    {
        public void getLatestNews(NewsDownloader downloader) 
        {
            downloader.download();
        }
    }
    
    添加工厂以创建新闻下载程序实例:

    public class NewsDownloaderFactory
    {
        public NewsDownloader getNewsDownloader(final Connection c)
        {
            final NewsDownloader downloader;
    
            if(c.getType().equals("Wifi"))
            {
                downloader = new FastNewsDownloader();
            }
            else if(c.getType().equals("3g"))
            {
                downloader = new NormalNewsDownloader();
            }
            else
            {
                downloader = new SlowNewsDownlaoder();
            }
    
            return (downloader);
        }  
    }
    
    然后你可以把它们放在一起:

    public void foo(final Connection c)
    {
        final NewsDownloader downloader;
        final NewsReader     reader;
    
        downloader = NewsDownloaderFactory.getNewsDownloader(c);
        reader = new NewsReader(downlaoder);    
    }
    
    既然您已经具备了所有这些,那么您就有了一些优势:

    • 您可以添加新的NewsDownloader实现,而不必在代码中添加大量if/else语句(假设您在多个位置创建NewsDownloader)
    • 您已将创建(工厂)本地化为单个if/else,从而使代码更清晰
    这意味着,如果您添加不同类型的新闻下载程序,您只需更改工厂,所有使用下载程序的代码就会神奇地工作


    如果代码中没有if/else语句,则在添加新的dowloader类型时会忘记修改其中一个语句,从而减少了可能出现的错误数量。

    附带建议:不要将字符串与==进行比较。请改用
    equals(…)
    equalsIgnoreCase(…)
    方法。我已更改了代码。这是我的一个错误,因为我的代码完全是草率的。我在飞行中做了上面的例子,这正是我所追求的。为什么它不被认为是理想的设计呢?根据我的经验,主要的原因是我建议的,因为你必须有两个地方的逻辑。理想情况下,新闻读者不必担心调用什么方法;相反,它可以将一些信息传递给工厂方法,并获得一个适合下载新闻的对象。因此,它不需要知道可能需要使用的各种不同的方法名称,它只需对返回给它的对象调用downloadNews()。我需要根据网络速度有条件地设置
    NewsDownloader
    的具体实现。我很好奇为什么界面会是一个好方法?因为客户端能够实现自己的下载逻辑,而不依赖于您在downloader类中编写的代码。很棒的答案@TofuBeer我删除了我的答案,因为这就是我解释的,另外+1表示非常解释的答案。+1这为我澄清了一切。事实上,我忽略了在多个地方使用
    NewsDownloader
    实例的可能性,这需要
    if/else
    语句。这太棒了,谢谢你。你还可以利用这个接口使现有的类成为NewsDownLaOrder(虽然我不喜欢这样做,如果我可以避免的话,每个类一个目的通常更好)。