还说城堡游戏,通过封装,我们降低了类和类之间的耦合,虽然我们没有实现加入新的方向,但是我们为可拓展型,打下了非常好的基础。
因为,我们封装之前是Room的细节是直接曝光给Game的,Game是直接访问Room的四个成员变量来掌握方向的出口,现在我们把Room的变量都做成私有了,提供了两个接口,一个接口给出了文字描述,一个接口是返回一个指定方向的那个房间。
用接口来实现聚合
●给Room类实现的新方法,把方向的细节彻底隐藏在Room类内部了
●今后方向如何实现就和外部无关了
有了这两个函数来说,意味着对于外界来说,Room以为的其他部分来说,Room内部,如何去表达每一个出口,如何建立起出口方向的字符串和在那个出口对应的房间之间的关系,就是Room自己说了算。
我们现在还是使用成员变量表示四个方向,如果我们还想增加方向,就需要采用更加灵活的表示方向和房间之间的关系了。
接下来,我们用容器来实现灵活性
●Room的方向是用成员变量表示的,增加或减少方向都要改变代码
●如果用Hash表来表示方向,那么方向就不是“硬编码”的了。
那方向就和Room本身没有关系了,更加的灵活
我们还通过
HashMash<键值类型,存储类型> 容器名 = new HashMap<键值类型,存储类型>();
public class Room { private HashMap<String,Room> exits = new HashMap<String, Room>(); }
当然,我们设置方向和数据之间的关系之后,我们的Room自然会报错,我们就不需要传入地点再判断那个方向是否有房间了
你叉叉————>
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;
}
我们只要给出方向和房间就可以了,当我们创建了对象之后,谁调用它,那他就可以根据传入的方向,来存入对应对象的方向的房间信息。
public void setExit(String dir, Room room){ exits.put(dir, room); }
那接下来的输出接下来出口的方向的成员函数也对应变了,
你叉叉
我们需要的是根据目前的房间,输出有出口的方向,我们需要输出的就是方向,也就是键值(键值就是方向,对应的元素就是方向上的房间)
我们需要拿到调用成员函数的容器键值,然后利用for-each循环,把方向存到StringBuffer就可以了
public String getExitDesc(){ StringBuffer sb = new StringBuffer(); for( String dir : exits.keySet()){ sb.append(dir); sb.append(' '); } return sb.toString(); }
接下来调整:
Room的成员函数是 管理输出 位移后房间 的函数public Room getExits(String direction){}
我们只用利用HashMash容器就可以了,传入方向键值,调用容器就可以得到,那个方向的房间了
public Room getExit(String direction){ return exits.get(direction); }
当然Room里面的成员函数内部虽然改变了,但是成员函数的名字没变,返回的参数也没变,所以Game调用Room,不受影响,唯一受影响的就是,我们改变了方向和房间的关系,所以在Game里创建对象,对对象进行关系赋值的时候会受影响,我们采用的是方向键值和那个方向的房间进行的匹配关系。
outside.setExit("east" , lobby); outside.setExit("south", study); outside.setExit("west", pub); lobby.setExit("west" , outside); pub.setExit("east" , outside); study.setExit("north" , outside); study.setExit("east" , bedroom); bedroom.setExit("west" , study); lobby.setExit("up" , pub); pub.setExit("down" , lobby);
那这样,我们就可以任意添加任意房间的任意方向的房间信息了。
我们就加入了上下的对应关系,那我们加入上下的关系,就和Room没有任何关系了,反正都是一一对应的关系。这个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.setExit("east" , lobby);
outside.setExit("south", study);
outside.setExit("west", pub);
lobby.setExit("west" , outside);
pub.setExit("east" , outside);
study.setExit("north" , outside);
study.setExit("east" , bedroom);
bedroom.setExit("west" , study);
lobby.setExit("up" , pub);
pub.setExit("down" , lobby);
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();
}
}
Room类:
package castle;
import java.util.HashMap;
public class Room {
private String description;
private HashMap<String,Room> exits = new HashMap<String, Room>();
public Room(String description)
{
this.description = description;
}
public void setExit(String dir, Room room){
exits.put(dir, room);
}
@Override
public String toString()
{
return description;
}
public String getExitDesc(){
StringBuffer sb = new StringBuffer();
for( String dir : exits.keySet()){
sb.append(dir);
sb.append(' ');
}
return sb.toString();
}
public Room getExit(String direction){
return exits.get(direction);
}
}