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

原创 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是单继承的,所以那些不能依赖于此的功能抽象应该选择接口。
抽象类的非抽象方法实现还可以在必要时给予派生类一些基本功能,嗯,这个是亮点,比起接口的空的方法还必须要实现一个空的看起来爽多了。
接口有利于更加抽象便捷的理解设计意图,但是不允许实体方法实现这个是个弊端,会造成实现该接口的大量派生类产生非常多的重复代码,这不便于维护。
重构这个东西,很多人理解成在设计时尽量考虑的很周全,这样有时候会浪费时间,为什么呢,代码->重构->模式  这种套路在实际开发中见的更多些,但提前做一些预期总会简便很多。


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


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

相关文章推荐

什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类

老帖了,但是还是想自己收录一下。最后也把自己对于这个问题的一些粗糙的理解记录下来。   在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是...

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

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

什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类

老帖了,但是还是想自己收录一下。最后也把自己对于这个问题的一些粗糙的理解记录下来。   在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。在这种情况下,各个对象内部是如何实现...

Linux DMA驱动构架分析

      以linux2.6.32中的S3C2440驱动为例进行分析,DMA驱动所对应的源码为linux-2.6.32.2/arch/arm/mach-s3c2440/dma.c,代码入口为:arc...

Java学习笔记之接口和抽象类的区别,及选择问题,看完之后就懂了。

abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力。 abstract class和inte...

抽象类及接口的实例及测试

  • 2008年04月28日 22:56
  • 29KB
  • 下载

java抽象类及接口的使用方法

  • 2015年01月24日 22:53
  • 89KB
  • 下载

java抽象类及接口

抽象类与接口是Java语言中对抽象概念进行定义的两种机制,他们让java更加具有强大的面向对象的能力。抽象类简单总结首先,在面向对象的领域一切都是对象。所有的对象都是通过类来描述的,但是并不能说所有的...

JavaSE--继承、抽象类及接口

1. 继承(extends) 如果多个类之间有多个相同的功能,可以将这些功能提取到一个类中,这个类为父类,其他类继承父类基本的功能。继承提高了代码的复用性,同时让类与类产生了关系,给面向对象的另一个特...

java中的final关键字、抽象类及接口的定义

final关键字 final:最终的       final:可以修饰 方法、成员变量、局部变量。       final  修饰类,则该类不能有子类 final   修饰方法:该方法不能被重...
  • RYJ359
  • RYJ359
  • 2017年07月23日 23:07
  • 99
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:抽象类及接口在设计时考虑的如何选择问题
举报原因:
原因补充:

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