以下为个人学习笔记和习题整理
课程:面向对象程序设计 ——Java 语言
- 浙江大学 - 翁恺 @ 中国大学 MOOC
https://www.icourse163.org/course/ZJU-1001542001
# 课堂笔记
# 消除代码复制
两个基本手段,就是函数和父类。
# 封装
对于类的设计来说,有两个核心术语:耦合和聚合。
耦合这个词指的是类和类之间的联系。
程序设计的目标是一系列通过定义明确的接口通信来协同工作的类。
耦合度反映了这些类联系的紧密度。
我们努力要获得低的耦合度,或者叫作松耦合 loose coupling
。
耦合度决定修改应用程序的容易程度。
在一个紧耦合的结构中,对一个类的修改也会导致 对其他一些类的修改。这是要努力避免的,否则,一点小小的改变就可能使整个应用程序发生 改变。另外,要想找到所有需要修改的地方,并一一加以修改,却是一件既困难又费时的事情。
在一个松耦合的系统中,常常可以修改一个类,但同时不会修改其他类,而且 整个程序还可以正常运作。
用封装来降低耦合。
# 可扩展性
可扩展性的意思就是代码的某些部分不需要经过修改就能适应将来可能的变化。
聚合与程序中一个单独的单元所承担的任务的数量和种类相对应有关,它是针对类或方法这样大小的程序单元而言的理想情况下,一个代码单元应该负责一个聚合的任务(也就是说,一个任务可以被看作是 一个逻辑单元)。
一个方法应该实现一个逻辑操作,而一个类应该代表一定类型的实体。
聚合理论背后的要点是重用:如果一个方法或类是只负责一件定义明确的事情,那么就很有可能在另外不同的上下文环境中使用。
遵循这个理论的一个额外的好处是,当程序某部分的代码需要改变时,在某个代码单元中很可能会找到所有需要改变的相关代码段。
用接口来实现聚合。
用容器来实现灵活性。
以框架 + 数据来提高可扩展性。
从程序中识别出框架和数据,以代码实现框架,将部分功能以数据的方式加载,这样能在很大程度上实现可扩展性。
# 课内项目
# 城堡游戏
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>(); | |
public Game() | |
{ | |
handlers.put("go", new HandlerGo(this)); | |
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("城堡外"); | |
lobby = new Room("大堂"); | |
pub = new Room("小酒吧"); | |
study = new Room("书房"); | |
bedroom = new Room("卧室"); | |
// 初始化房间的出口 | |
// outside.setExit(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); | |
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(); | |
// 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(); | |
showPrompt(); | |
} | |
// 以下为用户命令 | |
// private void printHelp() | |
// { | |
// System.out.print ("迷路了吗?你可以做的命令有:go bye help"); | |
// System.out.println ("如:\tgo east"); | |
// } | |
public 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; | |
// } | |
Room nextRoom = currentRoom.getExit(direction); | |
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(); | |
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(currentRoom.getExitDesc()); | |
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]); | |
String value = ""; | |
if(words.length > 1) | |
value = words[1]; | |
if (handler != null) { | |
handler.doCmd(value); | |
if(handler.isBye()) | |
break; | |
} | |
} | |
in.close(); | |
} | |
public static void main(String[] args) { | |
// Scanner in = new Scanner(System.in); | |
Game game = new Game(); | |
game.printWelcome(); | |
game.play(); | |
// 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.HashMap; | |
public class Room { | |
// public String description; | |
// public Room northExit; | |
// public Room southExit; | |
// public Room eastExit; | |
// public Room westExit; | |
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); | |
} | |
// 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(); | |
// 不用 String 然后字符串相加,因为那样系统开销会很大。 | |
for(String dir : exits.keySet()) { | |
sb.append(dir); | |
sb.append(' '); | |
} | |
// 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("south")) { | |
// ret = southExit; | |
// } | |
// if(direction.equals("west")) { | |
// ret = westExit; | |
// } | |
return exits.get(direction); | |
} | |
} |
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; | |
} | |
} |
package castle; | |
public class HandlerGo extends Handler { | |
public HandlerGo(Game game) { | |
super(game); | |
} | |
@Override | |
public void doCmd(String word) { | |
game.goRoom(word); | |
} | |
} |
package castle; | |
public class HandlerHelp extends Handler { | |
public HandlerHelp(Game game) { | |
super(game); | |
} | |
@Override | |
public void doCmd(String word) { | |
System.out.print("迷路了吗?你可以做的命令有:go bye help"); | |
System.out.println("如:\tgo east"); | |
} | |
} |
package castle; | |
public class HandlerBye extends Handler{ | |
public HandlerBye(Game game) { | |
super(game); | |
} | |
@Override | |
public boolean isBye() { | |
return true; | |
} | |
} |