城堡游戏的优化
在上一篇文章中JAVA学习笔记(四)城堡游戏,我们使用学到的类,继承,多态等知识完成了一个简单的文字城堡游戏,使用了Game和Room两个类,通过输入命令在地图上进行移动,获取帮助,开始游戏和结束游戏。但是在完成后我们发现整个游戏的代码质量不高,不具有扩展性,并且类与类之间的耦合性太高,所以我们尝试优化了一下城堡游戏,降低耦合性,消除代码的重复性,使我们的代码具有较高的扩展性,这样我们在以后维护代码,以及添加新的内容时更方便,同时也使得代码的可读性更高。当然我们也不是为了做这个游戏,让这个游戏以后也可以进行维护和扩展等等,我们只是通过这个例子来更加深入地理解扩展性,低耦合性的优势,以及怎么去优化代码。
一、消除代码的重复性
我们可以发现在之前的代码中,如果我们想在一开始就输出当前位置并输出接下来可移动的位置,必须要在Game类的printWelcome()函数中再添加一次代码:
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("north");
if(currentRoom.eastExit != null)
System.out.println("east");
if(currentRoom.southExit != null)
System.out.println("south");
if(currentRoom.westExit != null)
System.out.println("west");
System.out.println();
这样就和goRoom()函数中,当我们移动到下一个房间时,代码做的事情是一模一样的了,所以为了消除代码的重复性,我们构建了一个新的函数showPrompt(),在游戏开始的时候,和当我们进入下一个房间的时候,执行这个函数,输出接下来可移动的房间,并在这个函数中放入以下代码:
System.out.println("出口有:");
if(currentRoom.northExit != null)
System.out.println("north");
if(currentRoom.eastExit != null)
System.out.println("east");
if(currentRoom.southExit != null)
System.out.println("south");
if(currentRoom.westExit != null)
System.out.println("west");
System.out.println();
然后我们在printWelcome()函数和goRoom()函数中的最后都调用这个showPrompt()函数,这样就消除了代码的重复性,我们相同的代码只写了一段却调用了两次。
二、降低类与类之间的耦合性
我们可以发现我们在Room类和Game类中都有大量的代码与出口相关,我们在Room类中定义成员变量时都使用了public,为的就是可以让Game类在调用此类变量时更加方便,这就导致了Game类在运行时大量使用了Room类的成员变量,这样就产生了很高的耦合性。降低类与类之间的耦合性,让类与类之间保持距离是形成良好代码的关键所在。我们要尽量让成员变量私有化,在调用时仅在本类中进行调用,而在其他类中设计接口即可。
1.第一种耦合情况
首先还是showPrompt()函数中的那一部分,我们可以看到Game类的函数中直接调用了current对象的northExit,eastExit等的成员变量,所以我们把这一部分放到Room类中去,先将所有的成用变量私有化。
private String description;
private Room northExit;
private Room southExit;
private Room westExit;
private Room eastExit;
然后设计一个getExitDesc()函数:
public String getExitDesc(){
StringBuffer sb = new StringBuffer();
if ( northExit != null )
sb.append("north");
if ( southExit != null )
sb.append("south");
if ( westExit != null )
sb.append("west");
if ( eastExit != null )
sb.append("east");
return sb.toString();
}
这里我们使用了StringBuffer对象,因为String对象是一种没有办法进行修改的对象,如果使用String对象的话每一次使用都会产生一次新的String类型的对象,系统的执行速度就会降低。而StringBuffer 则是一种可以进行不断修改的对象类型。当成员变量不为null的时候,就append对应的方向即可,注意要返回toString类型,否则是无法正常显示Room类中的String类型的。 然后将Game类中的showPrompt()函数改为以下即可。这样就解开了一个耦合情况。
private void showPrompt(){
System.out.println(