Java 设计原则
一、城堡
1、
定义 Room 类。
定义了房子是什么,四个方向上的房子是什么。
package castle; public class Room { public String description;//描述位置 public Room northExit;//为什么是Room类型 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) //4个方向房子是什么。 { 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; } }
定义游戏
定义当前的房间是什么;
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("城堡外");//初始对象,给description赋值 lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("书房"); bedroom = new Room("卧室"); // 初始化房间的出口 outside.setExits(null, lobby, study, pub);//outside周围的四个房间 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(); System.out.println("现在你在" + currentRoom); System.out.print("出口有:"); if(currentRoom.northExit != null) System.out.print("north "); if(currentRoom.eastExit != null) System.out.print("east "); if(currentRoom.southExit != null) System.out.print("south "); if(currentRoom.westExit != null) System.out.print("west "); System.out.println(); } // 以下为用户命令 private void printHelp() { System.out.print("迷路了吗?你可以做的命令有:go bye help"); System.out.println("如:\tgo east"); } private void goRoom(String direction) { Room nextRoom = null;//下一个房间 if(direction.equals("north")) { nextRoom = currentRoom.northExit; } if(direction.equals("east")) { nextRoom = currentRoom.eastExit; } if(direction.equals("south")) { nextRoom = currentRoom.southExit; } if(direction.equals("west")) { nextRoom = currentRoom.westExit; } if (nextRoom == null) { System.out.println("那里没有门!"); } else { currentRoom = nextRoom;//更新所在房间 System.out.println("你在" + currentRoom); System.out.print("出口有: "); if(currentRoom.northExit != null) System.out.print("north "); if(currentRoom.eastExit != null) System.out.print("east "); if(currentRoom.southExit != null) System.out.print("south "); if(currentRoom.westExit != null) System.out.print("west "); 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; 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("城堡外");//初始对象,给description赋值 lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("书房"); bedroom = new Room("卧室"); // 初始化房间的出口 outside.setExits(null, lobby, study, pub);//outside连着三个房间 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 = null; if(direction.equals("north")) { nextRoom = currentRoom.northExit; } if(direction.equals("east")) { nextRoom = currentRoom.eastExit; } if(direction.equals("south")) { nextRoom = currentRoom.southExit; } if(direction.equals("west")) { nextRoom = currentRoom.westExit; } if (nextRoom == null) { System.out.println("那里没有门!"); } else { currentRoom = nextRoom;//更新所在房间 showPrompt(); } } public void showPrompt() //到达一个房间后的输出选择 { System.out.println("你在" + currentRoom); System.out.print("出口有: "); if(currentRoom.northExit != null) System.out.print("north "); if(currentRoom.eastExit != null) System.out.print("east "); if(currentRoom.southExit != null) System.out.print("south "); if(currentRoom.westExit != null) System.out.print("west "); 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; public class Room { private String description;//描述位置 private Room northExit;//???为什么是Room类型 private Room southExit; private Room eastExit; private 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() // 得到出口 将Game中的输出移到Room { // String ret=""; //这种方法开销大,每次都会产生一个新的String // if(northExit!=null) // ret+="north"; // if(eastExit!=null) // ret+="east"; // if(westExit!=null) // ret+="west"; // if(southExit!=null) // ret+="south"; // return ret; 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 selectNextRoom(String direction)//下一个房间 { Room nextRoom = null; if(direction.equals("north")) { nextRoom = this.northExit; } if(direction.equals("east")) { nextRoom = this.eastExit; } if(direction.equals("south")) { nextRoom = this.southExit; } if(direction.equals("west")) { nextRoom = this.westExit; } return nextRoom; } }
Room中的对象变量全部为private。
黄的将出口信息返回,绿的将下一个房间的信息返回。蓝的给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("城堡外");//初始对象,给description赋值 lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("书房"); bedroom = new Room("卧室"); // 初始化房间的出口 outside.setExits(null, lobby, study, pub);//outside连着三个房间 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; nextRoom=currentRoom.selectNextRoom(direction); if (nextRoom == null) { System.out.println("那里没有门!"); } else { currentRoom = nextRoom;//更新所在房间 showPrompt(); } } public void showPrompt() //到达一个房间后的输出选择 { System.out.println("你在" + currentRoom); System.out.print("出口有: "); System.out.print(currentRoom.getExitDesc());//调用Room类 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(); } }
四、可扩展性
1、
Room类
package castle; import java.util.HashMap; public class Room { private String description;//描述位置 private HashMap<String,Room> exist=new HashMap<String ,Room>();//HashMap 的键值对来存放,一间屋子里n个方向上的地方 public Room(String description) { this.description = description; } public void setExit(String dir,Room room)//往容器存放内容 { exist.put(dir,room); } @Override public String toString() { return description; } public String getExitDesc() // 得到容器中的出口(键) { StringBuffer sb=new StringBuffer();//这种方法开销小 for(String dir:exist.keySet())//遍历键 { sb.append(dir); sb.append(" "); } return sb.toString(); } public Room selectNextRoom(String direction)//下一个房间 { return exist.get(direction);//得到键对应的值 } }
2、Game类
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("城堡外");//初始对象,给description赋值 lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("书房"); bedroom = new Room("卧室"); // 初始化房间的出口 outside.setExit("east", lobby);//outside连着三个房间 outside.setExit("south", study); outside.setExit("west",pub); lobby.setExit("west", outside); lobby.setExit("up", bedroom);//自由增加房间各个出口 pub.setExit("west",outside); study.setExit("north",outside); study.setExit("east",bedroom); bedroom.setExit("west", study); bedroom.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; nextRoom=currentRoom.selectNextRoom(direction); if (nextRoom == null) { System.out.println("那里没有门!"); } else { currentRoom = nextRoom;//更新所在房间 showPrompt(); } } public void showPrompt() //到达一个房间后的输出选择 { System.out.println("你在" + currentRoom); System.out.print("出口有: "); System.out.print(currentRoom.getExitDesc());//调用Room类 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(); } }
本质上,是容器一一对应的关系。一个方向,定了一个房间。用容器来存放方向和房间。
五、框架+数据提高可扩展性
将go bye help 分别对应一个函数,也就是main()里只调用,而不输出。
5.1 定义一个父类,和三个子类来表示输出的函数
父类
package castle; public class Handler { protected Game game;//为输出函数准备 public Handler(Game game)//构造器 { this.game=game; } public void doCmd(String word) {}; public boolean isBye() { return false; } }
bye子类
package castle; public class HandlerBye extends Handler { public HandlerBye(Game game)//构造器 { super(game); } @Override public boolean isBye() { // TODO Auto-generated method stub return true; } }
help 子类
package castle; public class HandlerHelp extends Handler { public HandlerHelp(Game game)//构造器 { super(game); } @Override public void doCmd(String word) { System.out.println("迷路了吗?你可以做的命令有:go bye help"); System.out.println("如:\tgo east"); } }
go 子类
package castle; public class HandlerGo extends Handler { public HandlerGo(Game game) { super(game); } @Override public void doCmd(String word) { // TODO Auto-generated method stub game.goRoom(word); } }
2、Room类
package castle; import java.util.HashMap; public class Room { private String description;//描述位置 private HashMap<String,Room> exist=new HashMap<String ,Room>(); public Room(String description) { this.description = description; } public void setExit(String dir,Room room) { exist.put(dir,room); } @Override public String toString() { return description; } public String getExitDesc() // 得到出口 将Game中的输出移到Room { StringBuffer sb=new StringBuffer();//这种方法开销小 for(String dir:exist.keySet()) { sb.append(dir); sb.append(" "); } return sb.toString(); } public Room selectNextRoom(String direction)//下一个房间 { return exist.get(direction); } }
3、Game类
package castle; import java.util.HashMap; import java.util.Scanner; public class Game { private Room currentRoom;//目前房间 private HashMap<String,Handler> handlers=new HashMap<String,Handler>();//存放 (go help bye 所对应的Handler(game))函数定义为类。 public Game() { handlers.put("go",new HandlerGo(this));//将go和Game对应 handlers.put("bye",new HandlerBye(this)); handlers.put("help",new HandlerHelp(this)); createRooms(); } private void createRooms() { Room outside, lobby, pub, study, bedroom; // 制造房间 outside = new Room("城堡外");//初始对象,给description赋值 lobby = new Room("大堂"); pub = new Room("小酒吧"); study = new Room("书房"); bedroom = new Room("卧室"); // 初始化房间的出口 outside.setExit("east", lobby);//outside连着三个房间 outside.setExit("south", study); outside.setExit("west",pub); lobby.setExit("west", outside); lobby.setExit("up", bedroom); pub.setExit("west",outside); study.setExit("north",outside); study.setExit("east",bedroom); bedroom.setExit("west", study); bedroom.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(); } public void goRoom(String direction) { Room nextRoom; nextRoom=currentRoom.selectNextRoom(direction); if (nextRoom == null) { System.out.println("那里没有门!"); } else { currentRoom = nextRoom;//更新所在房间 showPrompt(); } } public void showPrompt() //到达一个房间后的输出选择 { System.out.println("你在" + currentRoom); System.out.print("出口有: "); System.out.print(currentRoom.getExitDesc());//调用Room类 System.out.println(); } public void play()//输出 { Scanner in = new Scanner(System.in);//输入 while ( true ) { String line = in.nextLine(); String[] words = line.split(" "); Handler handler=handlers.get(words[0]);//得到 键words所对应的值(go help bye)得到的是game,已经对应起来了。 String value=""; if(words.length>1) value=words[1];//help时,value是空的,区别go east、elp 和 bye if(handler!=null) { handler.doCmd(value);//有值时跳转HandlerGo,没有值时输出help if (handler.isBye()) break; } } System.out.println("感谢您的光临。再见!"); in.close(); } public static void main(String[] args) { Game game = new Game();//新的游戏对象 game.printWelcome();//输入初始欢迎信息 game.play(); } }