抽象类及接口在设计时考虑的如何选择问题

原创 2012年03月25日 04:43:24
关于抽象类和接口的相关视频里有,这就不说了,老房问了一个特别无语的问题,用我的话说就是钻牛角尖,但是这也涉及到了设计层面的犯愁,所以我还是找找了资料看看了,下边简单的给大家说说吧。
老房的问题是,如果抽象类里边没有任何抽象的成员,这样有什么实际的价值。


首先,我们假设需要一个电脑类Computer类,电脑有开机关机,那么这里我们选择抽象类还是接口呢?

package org.it;

public class MyComputer
{
	
}

abstract class Computer
{
	abstract void open();
	abstract void close();
}

interface Computer
{
	void open();
	void close();
}


这里就涉及了第一个问题,当你设计时,开和关是两个功能,而这两个功能都是独立的,但是他们又属于电脑,这是电脑的开关,所以应该是属于电脑的功能。但是换个角度,开关也不见得是电脑独有的,电视也有开关。而不论是抽象类,还是接口似乎都能达到目的。我们这么来弄

package org.it;

public class MyComputer extends Computer
{
	
}

abstract class Computer implements PowerSwitch
{
	
}

interface  PowerSwitch
{
	void open();
	void close();
}


这里电源开关是一个接口,任何东西实现他都能具有开关功能,所以我们采用一个抽象类Computer实现它,这样我的电脑就也具有了这个电源开关的功能。这样看起来更合逻辑,因为电源开关可以被比如电视类实现然后继续派生知道长虹 tcl的具体的实体类等等,而不是长虹电视还要继承Computer类来获得电源开关这个功能,难道世界乱套了?

这里涉及到第二个问题,电脑分很多种,比如华硕的,比如联想的,比如等等。

package org.it;

class AsusComputer extends Computer
{


	@Override
	public void open()
	{
	
	}


	@Override
	public void close()
	{
	
	}
}

class LenovoComputer extends Computer
{


	@Override
	public void open()
	{
	
	}


	@Override
	public void close()
	{
	
	}
}

abstract class Computer implements PowerSwitch
{
	
}


interface  PowerSwitch
{
	void open();
	void close();
}

写到这真就是蛋疼死了,为什么呢,因为你马上就要被疯狂的代码给累死,假设我们要根据不同的品牌做不一样的电源开源,比如有的带电压保险,比如有的可能还会同时打开显示器,在比如。。。我靠,如果有100个品牌,我们得写多少代码,那不是苦逼死了。我们可以整理下思路,好好想想怎么能让工作轻松些,这似乎是个不错的主意。

class AsusComputer extends Computer
{


	@Override
	public void open()
	{
		//给电脑接通电源
		//检查电压,如果超标则断开电源
	}


	@Override
	public void close()
	{
		//关闭电脑电源
	}
}


class LenovoComputer extends Computer
{


	@Override
	public void open()
	{
		//给电脑接通电源
		//给显示器接通电源
	}


	@Override
	public void close()
	{
		//关闭电脑电源
	}
}


这里没写具体代码,都是拿注释表示一下,嗯,应该都能明白是什么意思,我们可以仔细看下,其实不管什么牌子型号的电脑,肯定打开电脑电源和关闭电脑电源都是肯定有的。那么抽象的思想是什么?是不是把那些共有的抽离出去?那么代码为什么就不行?貌似谁也没说过对吧,so,我们这样
class AsusComputer extends Computer
{


	@Override
	public void open()
	{
		//检查电压,如果超标则断开电源
		super.open();
	}
}


class LenovoComputer extends Computer
{


	@Override
	public void open()
	{
		//给显示器接通电源
		super.open();
	}
}


abstract class Computer implements PowerSwitch
{
	public void open()
	{
		//给电脑接通电源
	}
	
	public void close()
	{
		//关闭电脑电源
	}
}


从代码我们开的出来,所有相同的代码我们全部都抽离到了Computer类里边,谢天谢地,终于不用写100次的打开电脑电源和关闭电源的代码了,话说就算你复制粘贴的话200遍这也不是啥事情吧。那么现在有个问题,既然我们已经这么抽离出来了,是不是所有的电脑都具备了电源开关?我们是否还是有必要让Computer类实现PowerSwitch类呢,这里就看我们是否有其他需求,比如说我还有电视要用这个功能,那么我们可以把他留下用来理解设计意图,但我们没有电视这个类,所以我们可以把这个实现接口去掉,因为这个Computer已经具有了这个电源开关的功能。

还有一个原因等下说,我们在考虑下,假设华硕的电脑有摄像头,联想的没有,这种情况下怎么办?我们肯定不能写在Computer类里,对吧,因为你写了,那么所有的电脑就都有摄像头了,这不合规矩。那么只能用接口来实现了,谁实现了谁就有摄像头。

package org.it;

class AsusComputer extends Computer implements Camera
{


	@Override
	public void open()
	{
		//检查电压,如果超标则断开电源
		super.open();
	}
	
	@Override
	public void Photograph()
	{
		//进行拍照
	}
}


class LenovoComputer extends Computer
{


	@Override
	public void open()
	{
		//给显示器接通电源
		super.open();
	}
}


abstract class Computer
{
	public void open()
	{
		//给电脑接通电源
	}
	
	public void close()
	{
		//关闭电脑电源
	}
}
interface Camera
{
	void Photograph();
}


到这里我相信大家应该差不多也明白了什么情况做什么选择,以及抽象类的非抽象方法的应用价值。

简单的来说就是,所有的子类所必须共有的成员以及方法,以及方法的实现代码都要抽离到抽象类里,而子类不必要的方法功能可以通过接口来实现,这在理解上有本质的区别。
抽象类的实体方法可以用来简化编写,便于维护,所以我们还是应该尽量的去考虑抽象类的派生类具体情况来抽离代码进行重构,但有一点java是单继承的,所以那些不能依赖于此的功能抽象应该选择接口。
抽象类的非抽象方法实现还可以在必要时给予派生类一些基本功能,嗯,这个是亮点,比起接口的空的方法还必须要实现一个空的看起来爽多了。
接口有利于更加抽象便捷的理解设计意图,但是不允许实体方法实现这个是个弊端,会造成实现该接口的大量派生类产生非常多的重复代码,这不便于维护。
重构这个东西,很多人理解成在设计时尽量考虑的很周全,这样有时候会浪费时间,为什么呢,代码->重构->模式  这种套路在实际开发中见的更多些,但提前做一些预期总会简便很多。


由于我的层次比较低,关于这些的更高级应用思想我也不知道,呵呵


话说老房你在问这么蛋疼的问题,我真心的爆你菊花。。。

包装类、final关键字、抽象类、抽象方法’

要备考,已经有好久没有接触java了,今天考完一科,赶紧复习一下,免得全部忘记了。 在上次课上,主要讲了三个方面:包装类的定义及其使用方法、由final关键字修饰的类和方法、抽象类和方法的使用。 1、...
  • mnv22172
  • mnv22172
  • 2016年07月01日 19:05
  • 266

JAVA中接口和抽象类的妙用-我自己也不知道这个是什么设计模式

抽象类写流程,接口规定必须实现的行为 首先我有一个这样的需求,有一个接收数据的程序,有多种报文格式,且每一种报文对应一个handler(这个报文的处理类),当有新的报文来临,程序判断由哪种han...
  • tjzhuorui
  • tjzhuorui
  • 2017年03月29日 14:04
  • 594

回答为什么“接口和抽象类大部分情况可以互相代替,一般情况接口优先选择'”?

 为什么优先使用接口呢?比如,现在有一个具体类,提供类的行为(使用硬代码)。现在,要提供类似的行为,并且实现动态的可插入,也就是说,能够动态地决定使用哪种实现。一个很容易想到的做法,就是提供该类一个抽...
  • yinyuan1987
  • yinyuan1987
  • 2008年03月30日 09:42
  • 1736

抽象类和接口的区别是什么?在使用上是如何选择的?

定义: 1、声明方法的存在而不去实现它的类被叫做抽像类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstra...
  • hjp1137
  • hjp1137
  • 2015年09月16日 15:27
  • 952

怎样设计抽象类

最近在做类设计时,正好有一个关于抽象类的定义,我顺便把定义抽象类的两种机制总结了一下,供大家参考。在java中大家都知道对抽象类定义进行支持的两种机制(abstract和interface),因为这两...
  • xrqiu
  • xrqiu
  • 2009年06月10日 10:35
  • 524

抽象类及接口在设计时考虑的如何选择问题

关于抽象类和接口的相关视频里有,这就不说了,老房问了一个特别无语的问题,用我的话说就是钻牛角尖,但是这也涉及到了设计层面的犯愁,所以我还是找找了资料看看了,下边简单的给大家说说吧。 老房的问题是,如...
  • dreamsky1989
  • dreamsky1989
  • 2012年03月25日 04:43
  • 1109

接口的作用,和抽象类之间的选择

前俩天有个弟弟和我说他不理解接口,我心里想接口有啥不好理解。想到了平时项目中的应用。瞬间想到的了,为啥我要用接口?我都想不到它切实的优点,和使用的必要性。 细思极恐,满身冷汗。一直都是刻板的套用,知道...
  • qq_34155601
  • qq_34155601
  • 2017年03月22日 17:43
  • 163

java中抽象类,接口,多态!

部分参考自:http://www.knowsky.com/539471.html 抽象类: 1.抽象类用abstract修饰 2.如果一个类里有一个以上的抽象方法,则该类必须声明为抽象类,该方法...
  • u011918771
  • u011918771
  • 2014年12月05日 11:04
  • 558

抽象类及接口

4抽象类及接口 4.1 final关键字 1. final关键字在Java中被称为完结器,表示最终的意思。 2. final关键字可以声明类、属性和方法: 定义:final class 类名...
  • qq_31126879
  • qq_31126879
  • 2016年08月20日 11:11
  • 148

抽象类与接口该怎么选用

抽象类与接口该怎么选用
  • zenghb
  • zenghb
  • 2016年04月22日 17:28
  • 331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:抽象类及接口在设计时考虑的如何选择问题
举报原因:
原因补充:

(最多只允许输入30个字)