上一个城堡游戏,没有bug ,可以运行,但不代表是好代码,衡量一个代码是不是好代码,要考虑
以后我们增加新功能的时候,是不是可以很快捷
增加可扩展性
●可以运行的代码 != 良好的代码
●对代码做维护的时候最能看出代码的质量
●如果想要增加一个方向,如down 或up
那这个程序,几乎是所有的部分,都要被你改掉,代码不具有可扩展性
用封装来降低耦合
•Room和Game类都有大量的代码和出口相关
•尤其是Game类中大量使用了Room类的成员变量
•类和类之间的关系称作耦合
•耦合越低越好,保持距离是形成良好代码的关键
有一个问题就是,Room里面的成员变量,我们说非不得已,不用Public,然而我们用了之后,
在Game里面一直重复调用Room里面的成员变量,我们说,这是不好的
所以,把Room里面的成员变量变成private
然而,改完之后,由于Game里面调用Room的成员变量不可访问了,
当然,这时候会有同学说,我们可以在Room里面为每个成员变量设置一个public
的返回值的成员函数,然后在Game里面调用,这是一个无可奈何的做法。
我们现在要理解的是,为什么我们需要调用Room里面的成员函数,我们在Game里
面,要通过判断Room的成员变量是否为空,从而判断那个方向是否有出口,那我们为什么不直接
返回有没有出口呢?这说明,我们没必要在Game类里重复调用Room里面的成员变量,直接
让Room返回Game想要的结果就可以了,把工厂搬出去,在源头生产,更方便。
所以,我们现在要做的就是,要把出口,全部判断出来,并返回给Game
在Room里面,通过StringBuffer 来存储出口
创建成员变量
public String getExitDesc(){
StringBuffer sb = new StringBuffer();
if(northExit != null)
sb.append("north");
if(eastExit != null)
sb.append("east");
if(westExit != null)
sb.append("west");
if(southExit != null)
sb.append("south");
return sb.toString();
}
那在Game里面判断出口的成员函数public void showPeompt(){}就改变了,就可以直接调用Room里面的成员函数,返回对应的参数就可以了
public void showPrompt(){
System.out.println("现在你在" + currentRoom);
System.out.print("出口有:");
System.out.println(currentRoom.getExitDesc());
System.out.println();
}
另外,我们在Game类里面,private void goRoom(String direction){ }里面
传入方向String direction,判断赋值下一个房间的时候,我们也重复调用了Room的成员变量,
同样我们让Room自己做这个事情,
我们在Room里面创建一个成员变量,根据传入的方向参数String direction,再调用自己的成员变量,返回给Game 对应方向的房间
public Room getExit(String direction){
Room ret = null;
if(direction.equals("north")){
ret = northExit;
}
if(direction.equals("east")){
ret = eastExit;
}
if(direction.equals("west")){
ret = westExit;
}
if(direction.equals("south")){
ret = southExit;
}
return ret;
}
然后Game类,private void goRoom(){} 这个传入方向,出房间的成员函数就变了,它直接调用Room里面的成员函数,就可以得出下一个方向房间的信息了。
private void goRoom(String direction)
{
Room nextRoom = currentRoom.getExit(direction);
if (nextRoom == null) {
System.out.println("那里没有门!");
}
else {
currentRoom = nextRoom;
showPrompt();
}
}
现在Game和Room直接就松了很多,这样,game就不会直接用Room的成员变量了。
我们实现了两个接口,这是利用了封装来降低耦合,但是我们还没有解决拓展性问题。
更改过的源代码:
package castle;
import java.util.Scanner;
public class Game {
private Room currentRoom;
public Game()
{
createRooms();
}
private void createRooms()
{
Room outside, lobby, pub, study, bedroom;
// 制造房间
outside = new Room("城堡外");
lobby = new Room("大堂");
pub = new Room("小酒吧");
study = new Room("书房");
bedroom = new Room("卧室");
// 初始化房间的出口
outside.setExits(null, lobby, study, pub);
lobby.setExits(null, null, null, outside);
pub.setExits(null, outside, null, null);
study.setExits(outside, bedroom, null, null);
bedroom.setExits(null, null, null, study);
currentRoom = outside; // 从城堡门外开始
}
private void printWelcome() {
System.out.println();
System.out.println("欢迎来到城堡!");
System.out.println("这是一个超级无聊的游戏。");
System.out.println("如果需要帮助,请输入 'help' 。");
System.out.println();
showPrompt();
}
// 以下为用户命令
private void printHelp()
{
System.out.print("迷路了吗?你可以做的命令有:go bye help");
System.out.println("如:\tgo east");
}
private void goRoom(String direction)
{
Room nextRoom = currentRoom.getExit(direction);
if (nextRoom == null) {
System.out.println("那里没有门!");
}
else {
currentRoom = nextRoom;
showPrompt();
}
}
public void showPrompt(){
System.out.println("现在你在" + currentRoom);
System.out.print("出口有:");
System.out.println(currentRoom.getExitDesc());
System.out.println();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Game game = new Game();
game.printWelcome();
while ( true ) {
String line = in.nextLine();
String[] words = line.split(" ");
if ( words[0].equals("help") ) {
game.printHelp();
} else if (words[0].equals("go") ) {
game.goRoom(words[1]);
} else if ( words[0].equals("bye") ) {
break;
}
}
System.out.println("感谢您的光临。再见!");
in.close();
}
}
package castle;
public class Room {
public String description;
public Room northExit;
public Room southExit;
public Room eastExit;
public Room westExit;
public Room(String description)
{
this.description = description;
}
public void setExits(Room north, Room east, Room south, Room west)
{
if(north != null)
northExit = north;
if(east != null)
eastExit = east;
if(south != null)
southExit = south;
if(west != null)
westExit = west;
}
@Override
public String toString()
{
return description;
}
public String getExitDesc(){
StringBuffer sb = new StringBuffer();
if(northExit != null)
sb.append("north");
if(eastExit != null)
sb.append("east");
if(westExit != null)
sb.append("west");
if(southExit != null)
sb.append("south");
return sb.toString();
}
public Room getExit(String direction){
Room ret = null;
if(direction.equals("north")){
ret = northExit;
}
if(direction.equals("east")){
ret = eastExit;
}
if(direction.equals("west")){
ret = westExit;
}
if(direction.equals("south")){
ret = southExit;
}
return ret;
}
}