黑马程序员——面向对象16:多态应用实例

------- android培训java培训、期待与您交流! ----------

1. 应用一

需求:模拟电脑的运行。

分析1:我们假设只要主板能够运行,电脑就能使用。

代码1:

/*
	定义主板类,其内包含一个run方法,表示主板运行。
*/
class MainBoard
{
	public void run()
	{
		System.out.println("MainBoardrun");
	}
}
class PolyTest//Poly是polymorphic——多态的简写,下同
{
	public static void main(String[] args)
	{
		//创建主板对象,并调用其run方法,运行电脑。
		MainBoard mb= new MainBoard();
		mb.run();
	}
}
运行结果为:

MainBoard run

这样的设计就相当于,一个主板上装了CPU、内存和显卡,都是焊死的,然后用机箱一装就可以使用。这样设计最大的弊端就是:后期的扩展性非常差,连上网和听音乐都无法实现,因为即使有网卡和声卡,都无法安装到主板上。

 

分析2:为了满足上网和听音乐的需求,我们在主板上又焊上了网卡和声卡。

代码2:

class MainBoard
{
	public void run()
	{
		System.out.println("MainBoardrun");
	}
	public void useNetCard(NetCardnc)
	{
		nc.open();
		nc.close();
	}
	public void useSoundCard(SoundCardsc)
	{
		sc.open();
		sc.close();
	}
}
class NetCard
{
	public void open()
	{
		System.out.println("NetCardopen");
	}
	public void close()
	{
		System.out.println("NetCardclose");
	}
}
class SoundCard
{
	public void open()
	{
		System.out.println("SoundCardopen");
	}
	public void close()
	{
		System.out.println("SoundCardclose");
	}
}
class PolyTest2
{
	public static void main(String[] args)
	{
		MainBoard mb= new MainBoard();
		mb.run();
		mb.useNetCard(newNetCard());
		mb.useSoundCard(newSoundCard());
	}
}
运行结果:

MainBoard run

NetCard open

NetCard close

SoundCard open

SoundCard close

从结果上看,这样的使用方式还不错。但是,扩展性依旧很差,如果想继续对CPU、内存和显卡等配件进行升级,就又要对主板进行改动,折射到代码上就是要不停的修改代码,非常麻烦。另一方面,不同厂商生产的配件并不一定兼容,这又是一个问题。

 

分析3:从前面两种情况来看,各个配件和主板之间的耦合性太高,从而导致扩展性很低。那么为了降低配件与主板之间的耦合性,各大厂商之间经过协商想出了一个解决方法:在主板上预先安装各种插槽,比如CPU插槽、内存插槽以及其他所有板卡的插槽。这些插槽的设计都符合所谓的PCI标准,电脑配件的设计只要符合这种标准,就可以正常使用。有了这种通用插槽的设计,可以任意更换符合这种插槽标准的配件,降低了主板和配件之间的耦合性,并且如果后期又有了其他功能的板卡只要符合这个插槽的标准就可以,大大提升了主板的扩展性。

代码3:

/*
	用接口的方式定义PCI插槽标准
	配件只要实现PCI插槽接口,就可以被主板使用
*/
interface PCI
{
	public abstract void open();
	public abstract void close();
}
class MainBoard
{
	public void run()
	{
		System.out.println("MainBoardrun");
	}
	//定义使用PCI设备的方法
	//接口型引用指向自己的子类对象,比如PCI p = new NetCard();
	public void usePCI(PCI p)
	{
		/*
			if语句的判断,可以保证即使PCI插槽上没有配件
			至少能保证主板可以正常运行
		*/
		if(p!= null)
		{
			p.open();
			p.close();
		}
       }
}
class NetCard implements PCI
{
	public void open()
	{
		System.out.println("NetCardopen");
	}
	public void close()
	{
		System.out.println("NetCardclose");
	}
}
class SoundCard implements PCI
{
	public void open()
	{
		System.out.println("SoundCardopen");
	}
	public void close()
	{
		System.out.println("SoundCardclose");
	}
}
class PolyTest2
{
	public static void main(String[] args)
	{
		MainBoard mb = new MainBoard();
		mb.run();
		/*
			通过这样的设计,不必去改动“主板”类的代码
			只需要在主函数,添加调用新配件的代码即可
		*/
		mb.usePCI(newNetCard());
		mb.usePCI(newSoundCard());
	}
}
运行结果为:

MainBoard run

NetCard open

NetCard close

SoundCard open

SoundCard close

通过使每个配件实现PCI接口,然后在主板中定义使用实现了PCI接口配件的方法,通过多态的形式,用PCI型引用接收其子类对象,并调用子类对象的方法,即使后期再出现其他配件,只要实现PCI接口都可以被主板使用,大大提高了主板的扩展性。

2. 应用二

需求:模拟数据库的应用。这里我们假设需要操作的数据是用户信息,操作数据库的方式为JDBC。因为这个示例仅仅是模拟,因此部分代码为伪代码,能够说明问题即可。

分析1:通常,数据库的使用过程如下:

1) 连接数据库;

2) 操作数据库:

增(Create)

删(delete)

改(update)

查(research)

3) 关闭数据库连接。

代码4:

//定义数据库操作类
class UserInfoByJDBC
{
	/*
		无论对数据库进行何种操作,首先都要连接数据库,
		操作完毕以后,必须关闭连接,
		这是因为,每一个服务器的用户连接数是有限的,
		如果某个用户长时间不断开与数据库的连接,
		势必造成其他用户无法连接
	*/
	//这里仅定义两个方法用于演示
	public void add(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句添加数据;
		//3.关闭连接。
	}
	public void delete(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句删除数据;
		//3.关闭连接。
	}
}
//定义一个虚拟的用户类
class User{}
 
class DBOperator
{
	public static void main(String[] args)
	{
		//首先创建数据库操作对象
		UserInfoByJDBC uibj = new UserInfoByJDBC();
             
		//开始通过该对象对外提供的方法,对数据库进行操作
		//增加用户信息
		uibj.add(newUser());
		//删除用户信息
		uibj.delete(newUser());
	}
}
通过上面的代码就简单演示了通过JDBC的方式连接数据库的过程。如果后期发现通过JDBC的方式比较麻烦,我们就想通过Hibernate等更为便捷的方式操作数据库。这就又涉及到了代码的大面积修改,因此是不可取的。

 

分析2:那么同样,首先我们还是要降低连接数据的方式(JDBC和Hibernate)与数据库操作主程序之间的耦合性,因为无论使用什么方式连接数据库,对数据库的操作内容都是增删改查,只不过两种方式的具体实现代码不同而已。这就和第一个例子的思路是一样的,我们事先定义一个接口表示某种规则,只要JDBC和Hibernate满足这一规则(实现这个接口),那么操作数据库的主程序就可以使用这两种方式操作数据库。

代码5:

/*
	定义一个操作数据库的接口,里面封装了操作数据的方法
	而具体的执行代码由实现了该规则子类定义
*/
interface UserInfoDao
{
	public abstract void add(User user);
	public abstract void delete(User user);
}
//定义数据库操作类,实现UserInfoDao接口,并复写其中的方法
class UserInfoByJDBC implements UserInfoDao
{
	public void add(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句添加数据;
		//3.关闭连接。
	}
	public void delete(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句删除数据;
		//3.关闭连接。
	}
}
class UserInfoByHibernate implementsUserInfoDao
{
	public void add(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句添加数据;
		//3.关闭连接。
	}
	public void delete(User user)
	{
		//1.连接数据库;
		//2.使用SQL语句删除数据;
		//3.关闭连接。
	}
}
//定义一个虚拟的用户类
class User{}
 
class DBOperator
{
	public static void main(String[] args)
	{
		/*
			通过接口引用指向其子类对象
			如果后期想要使用Hibernate等新方法操作数据库
			只需要修改对象创建语句右边的类名即可
			而不需要修改其他代码
		*/
		UserInfoDao uid = new UserInfoByJDBC();
		//增加用户信息
		uid.add(newUser());
		//删除用户信息
		uid.delete(newUser());
}
通过上述这种接口加多态的形式定义并创建数据库访问对象,降低了耦合性,提高了扩展性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值