Java 重写方法与多次实现方法
假设我有一个从web下载新闻提要的类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
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
更抽象的设计会给新闻阅读器带来什么好处(如果有的话)
我希望人们不要认为这是一种欺骗!我只是想阐明抽象设计为我正在撰写的一个项目所解决的问题,我不知道你想把事情抽象化的原因是什么。一般规则:
- 抽象类用于代码重用
- 接口定义合同
- 应用控制反转原理,工厂模式有时可以提供帮助
更新:在代码中列出这些原则方面做得很好。您不一定会遇到问题,但有一种想法是,当新的网络连接被发明时,您需要同时更新新闻阅读器和新闻下载器。如果(例如)您使用了工厂模式,那么您可以这样做,即使用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(虽然我不喜欢这样做,如果我可以避免的话,每个类一个目的通常更好)。