21201701-陈荟光第二次学习总结
前言:
随着学习的不断深入,Java类设计的题目也愈加难了起来,近两周的作业难度更是达到了令人头皮发麻的程度。先不论继承多态的综合应用,单是设计那些数量繁多功能繁杂的类就已经让人头皮发麻。除此之外还有大量的数学领域的复杂计算,不禁让人怀疑人生。本篇报告选取了PTA题目集06的7-5、本次期中考试试题、超星作业中双向链表的设计以及第五次农夫过河的迭代实验,主要讲述关于我对容器、多态、继承的个人理解以及在设计上述实验时的思路。
设计与分析与采坑心得与改进建议:
ATM机类结构设计(一)
实验要求请参考https://images.ptausercontent.com/93fc7ad6-5e85-445a-a759-5790d0baab28.pdf
关于本次实验,我的设计思路大致分为如下几个阶段:
一、大方向设计
根据实验手册中的信息,可以知道,本实验中涉及到的实体有:银行、用户、银行账户、银行卡和ATM机;涉及到的抽象信息有:用户名、隶属银行、银行账号、余额、隶属卡号和密码和ATM机编号。由此一来,我们便可以以填空的形式构建类的初始信息。
首先,根据我们日常生活中的经验可以知道,用户名是用户的基础信息,而每个用户可以拥有多个银行账户,所以用户类下应该含有两个属性:用户名和银行账户列表。
然后是银行账户类。银行账号是识别银行账户的根本信息,而银行账户都是隶属于某个银行的,且用户的存款也是存到账户中,每个银行账户又可以开通多张银行卡,故银行账户类下应该含有四个属性:银行账号、隶属银行、存款数额以及银行卡列表。
再然后是银行卡类。在本实验情境中,不难看出,银行卡只是从银行账户取款的手段,也就是我们俗称的“工具人”,故银行卡的属性只有银行卡号和密码。
关于银行类,由于本题中并未调用其方法,所以我仅将它作为一个参数,没有设计类;而ATM机类也仅仅是作为验证码一样的存在,同样是工具人,所以ATM机类的属性只需要ATM机编号和隶属银行便足以。
二、实体类方法设计
在设计实体类之前,我们需要知道存取款的原理。根据日常生活的经验,我们知道,要想取钱,首先得在ATM机上插入银行卡,然后输入密码,访问自己的银行账户,然后进行存取款等操作。这一系列的流程的实质是,用户在ATM机通过银行卡密访问银行数据库,银行的计算机会遍历数据库找到和银行卡号相匹配的账户,然后我们再进行操作。银行卡本身不进行任何操作,因此银行卡类除了setter和getter外不需要其他方法;而对于银行账户,首先我们要构建存取款方法,然后我们要为银行账户构建修改其名下的银行卡的方法,本实验中由于并不需要用到后者,因此我并没有构建这一方法;对于用户,首先,我们需要能访问我们的银行账户,所以我们需要一个方法来在所有账户中遍历,从而找到和我们使用的银行卡相匹配的方法,其次,我们需要拥有能设置我们的银行账户的方法,如开户和销户,本实验中虽然用不到,但我也顺手做了一对了;ATM机类仅供验证用,故只需要getter和setter用于获取其信息便足以。
三、业务类设计
在完成了对所有实体类的创建以后,我们要做的便是构建一个将所有实体类关联起来,在本实验中,我们要做的便是一个类似银行系统的业务类。
在实体类设计中,我们已经说明了银行系统的职业,这里就不再赘述。总的来说,我们的银行系统要做到以下两点:1.用户输入正确的卡密后访问其对应的账户;2.根据用户的输入调用其账户的对应方法,并给予反馈;3.检测用户是否有诸如跨行取款的不合法行为并给予相应的反馈。
为了完成上述需求,首先,我们需要创建一个静态的用户类容器作为数据库,用于记录下所有数据;然后我们需要创建一个静态的ATM类容器用于验证用户行为的合法性;我们需要构建方法用于检测用户的输入信息和用户行为的合法性并给出相应的反馈,另外针对不同的操作需要构建不同的方法(如存取款与查看余额)。至此,设计阶段已然完成,接下来便是代码实现了。
四、代码实现
最终代码:
1 import java.util.ArrayList; 2 import java.util.Scanner; 3 4 public class Main { 5 6 public static Scanner input = new Scanner(System.in); 7 8 public static void main(String[] args){ 9 10 Model model = new Model(); 11 //初始化ATM 12 Model.atms.add(new ATM("01", "中国建设银行")); 13 Model.atms.add(new ATM("02", "中国建设银行")); 14 Model.atms.add(new ATM("03", "中国建设银行")); 15 Model.atms.add(new ATM("04", "中国建设银行")); 16 Model.atms.add(new ATM("05", "中国工商银行")); 17 Model.atms.add(new ATM("06", "中国工商银行")); 18 //创建初始账户 19 Model.users.add(new User("杨过",new ArrayList<Account>() { 20 { 21 add(new Account("3217000010041315709", "中国建设银行", 10000.00, new ArrayList<Card>() { 22 { 23 add(new Card("6217000010041315709", "88888888")); 24 add(new Card("6217000010041315715", "88888888")); 25 } 26 })); 27 add(new Account("3217000010041315715", "中国建设银行", 10000.00, new ArrayList<Card>() { 28 { 29 add(new Card("6217000010041315718", "88888888")); 30 } 31 })); 32 } 33 })); 34 35 Model.users.add(new User("郭靖",new ArrayList<Account>() { 36 { 37 add(new Account("3217000010051320007", "中国建设银行", 10000.00, new ArrayList<Card>() { 38 { 39 add(new Card("6217000010051320007", "88888888")); 40 } 41 })); 42 } 43 })); 44 45 Model.users.add(new User("张无忌",new ArrayList<Account>() { 46 { 47 add(new Account("3222081502001312389", "中国工商银行", 10000.00, new ArrayList<Card>() { 48 { 49 add(new Card("6222081502001312389", "88888888")); 50 } 51 })); 52 add(new Account("3222081502001312390", "中国工商银行", 10000.00, new ArrayList<Card>() { 53 { 54 add(new Card("6222081502001312390", "88888888")); 55 } 56 })); 57 add(new Account("3222081502001312399", "中国工商银行", 10000.00, new ArrayList<Card>() { 58 { 59 add(new Card("6222081502001312399", "88888888")); 60 add(new Card("6222081502001312400", "88888888")); 61 } 62 })); 63 } 64 })); 65 Model.users.add(new User("韦小宝",new ArrayList<Account>() { 66 { 67 add(new Account("3222081502051320785", "中国工商银行", 10000.00, new ArrayList<Card>() { 68 { 69 add(new Card("6222081502051320785", "88888888")); 70 } 71 })); 72 add(new Account("3222081502051320786", "中国工商银行", 10000.00, new ArrayList<Card>() { 73 { 74 add(new Card("6222081502051320786", "88888888")); 75 } 76 })); 77 } 78 })); 79 model.work(); 80 } 81 82 } 83 84 85 class Model { 86 87 88 public static ArrayList<User> users = new ArrayList<>(); 89 public static ArrayList<ATM> atms = new ArrayList<>(); 90 91 private String pattern1 = "\\d{19}\\s+\\d+\\s+\\d+\\s+(\\+|-)?\\d+(\\.\\d+)?"; 92 private String pattern2 = "\\d{19}"; 93 94 public Model() { 95 } 96 97 public void work() { 98 while (true) { 99 String command = Main.input.nextLine(); 100 if (command.matches(pattern1)) { 101 changeDeposit(command); 102 } else if (command.matches(pattern2)){ 103 checkDeposit(command); 104 } else { 105 break; 106 } 107 } 108 } 109 110 public ATM searchATM(String ATMID) { 111 for (ATM atm:atms) { 112 if (atm.getNumber().equals(ATMID)) { 113 return atm; 114 } 115 } 116 System.out.println("Sorry,the ATM's id is wrong."); 117 System.exit(0); 118 return null; 119 } 120 121 public User searchUser(String cardID) { 122 for (User user:Model.users) { 123 for (Account account:user.getAccounts()) { 124 for (Card card:account.getCards()) { 125 if (card.getCardID().equals(cardID)) { 126 return user; 127 } 128 } 129 } 130 } 131 System.out.println("Sorry,this card does not exist."); 132 System.exit(0); 133 return null; 134 } 135 136 public void changeDeposit(String command) { 137 String[] imformation = command.split("\\s+"); 138 User user = searchUser(imformation[0]); 139 Account account = user.accessAccount(imformation[0], imformation[1]); 140 ATM atm = searchATM(imformation[2]); 141 if (!atm.validate(account.getBank())){ 142 System.out.println("Sorry,cross-bank withdrawal is not supported."); 143 System.exit(0); 144 } 145 double amount = -(Double.parseDouble(imformation[3])); 146 if (account.getDeposit() + amount < 0) { 147 System.out.println("Sorry,your account balance is insufficient."); 148 System.exit(0); 149 } else { 150 account.changeDeposit(amount); 151 if (amount >= 0) { 152 System.out.println(user.getUserName() + "在" + atm.getBankName() + "的" + imformation[2] + "号ATM机上存款¥" + String.format("%.2f", amount) + "\n当前余额为¥" + String.format("%.2f", account.getDeposit())); 153 } else { 154 System.out.println(user.getUserName() + "在" + atm.getBankName() + "的" + imformation[2] + "号ATM机上取款¥" + String.format("%.2f", -amount) + "\n当前余额为¥" + String.format("%.2f", account.getDeposit())); 155 } 156 } 157 } 158 159 public void checkDeposit(String cardID) { 160 User user = searchUser(cardID); 161 Account account = user.searchAccount(cardID); 162 System.out.printf("¥%.2f\n", account.getDeposit()); 163 } 164 165 } 166 167 168 class User { 169 170 private String userName; 171 private ArrayList<Account> accounts; 172 173 public User() { 174 // TODO Auto-generated constructor stub 175 } 176 177 public User(String userName, ArrayList<Account> accounts) { 178 super(); 179 this.userName = userName; 180 this.accounts = accounts; 181 } 182 183 public void openAccount(Account newAccount) { 184 accounts.add(newAccount); 185 } 186 187 public void closeAccount(Account newAccount) { 188 if (!accounts.remove(newAccount)) { 189 System.out.print("Sorry,this card does not exist."); 190 } 191 } 192 193 public Account accessAccount(String cardID, String password) { 194 for (Account account:accounts) { 195 for (Card card:account.getCards()) { 196 if (card.getCardID().equals(cardID)) { 197 if (card.getPassword().equals(password)) { 198 return account; 199 } else { 200 System.out.print("Sorry,your password is wrong."); 201 System.exit(0); 202 return null; 203 } 204 } 205 } 206 } 207 System.out.println("Sorry,this card does not exist."); 208 System.exit(0); 209 return null; 210 } 211 212 public Account searchAccount(String cardID) { 213 for (Account account:accounts) { 214 for (Card card:account.getCards()) { 215 if (card.getCardID().equals(cardID)) { 216 return account; 217 } 218 } 219 } 220 System.out.println("Sorry,this card does not exist."); 221 System.exit(0); 222 return null; 223 } 224 225 public String getUserName() { 226 return userName; 227 } 228 229 public void setUserName(String userName) { 230 this.userName = userName; 231 } 232 233 public ArrayList<Account> getAccounts() { 234 return accounts; 235 } 236 237 public void setAccounts(ArrayList<Account> accounts) { 238 this.accounts = accounts; 239 } 240 241 } 242 243 244 class Account { 245 246 private String AccountID; 247 private String bank; 248 private double deposit; 249 private ArrayList<Card> cards; 250 251 public Account(String accountID, String bank, double deposit) { 252 super(); 253 AccountID = accountID; 254 this.bank = bank; 255 this.deposit = deposit; 256 cards = new ArrayList<Card>(); 257 } 258 259 public Account(String accountID, String bank, double deposit, ArrayList<Card> cards) { 260 super(); 261 AccountID = accountID; 262 this.bank = bank; 263 this.deposit = deposit; 264 this.cards = cards; 265 } 266 267 public void changeDeposit(double amount) { 268 deposit += amount; 269 } 270 271 public String getAccountID() { 272 return AccountID; 273 } 274 275 public void setAccountID(String accountID) { 276 AccountID = accountID; 277 } 278 279 public String getBank() { 280 return bank; 281 } 282 283 public void setBank(String bank) { 284 this.bank = bank; 285 } 286 287 public double getDeposit() { 288 return deposit; 289 } 290 291 public void setDeposit(double deposit) { 292 this.deposit = deposit; 293 } 294 295 public ArrayList<Card> getCards() { 296 return cards; 297 } 298 299 public void setCards(ArrayList<Card> cards) { 300 this.cards = cards; 301 } 302 303 @Override 304 public boolean equals(Object obj) { 305 Account account = (Account) obj; 306 if (account.getAccountID().equals(AccountID)) { 307 return true; 308 } else { 309 return false; 310 } 311 } 312 313 } 314 315 316 class Card { 317 318 private String cardID; 319 private String password; 320 321 public Card() { 322 323 } 324 325 public Card(String cardID, String password) { 326 super(); 327 this.cardID = cardID; 328 this.password = password; 329 } 330 331 public String getCardID() { 332 return cardID; 333 } 334 335 public void setCardID(String cardID) { 336 this.cardID = cardID; 337 } 338 339 public String getPassword() { 340 return password; 341 } 342 343 public void setPassword(String password) { 344 this.password = password; 345 } 346 347 @Override 348 public boolean equals(Object obj) { 349 Card card = (Card) obj; 350 if (card.getCardID().equals(cardID)) { 351 return true; 352 } else { 353 return false; 354 } 355 } 356 357 } 358 359 360 class ATM { 361 362 private String number; 363 private String bankName; 364 365 public ATM() { 366 // TODO Auto-generated constructor stub 367 } 368 369 public ATM(String number, String bankName) { 370 super(); 371 this.number = number; 372 this.bankName = bankName; 373 } 374 375 public boolean validate(String bankName) { 376 if (this.bankName.equals(bankName)) { 377 return true; 378 } else { 379 return false; 380 } 381 } 382 383 public String getNumber() { 384 return number; 385 } 386 387 public void setNumber(String number) { 388 this.number = number; 389 } 390 391 public String getBankName() { 392 return bankName; 393 } 394 395 public void setBankName(String bankName) { 396 this.bankName = bankName; 397 } 398 399 }
PowerDesigner类图:

点线面问题
一、点线面问题(类设计)

由于类图指引过于清晰,故本部分仅提及一些编程技巧
1.在确认输入数据符合要求的情况下,可以使用.next()过滤空格;
2.浮点数保留数位可以先通过String.format()将浮点数转成需要的格式的字符串,然后使用Double.parseDouble()将字符串转换回浮点数,或使用Interge.parseInt()将字符串转换为整数;
以下是本人的源代码。
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 7 Scanner input = new Scanner(System.in); 8 9 Line line = new Line(new Point(input.nextDouble(), input.nextDouble()), new Point(input.nextDouble(), input.nextDouble()), input.next()); 10 11 line.display(); 12 } 13 14 } 15 16 17 class Point { 18 19 private double x; 20 private double y; 21 22 public Point() { 23 24 } 25 26 public Point(double x, double y) { 27 if (x > 0 && x <= 200 && y > 0 && y <= 200) { 28 this.x = x; 29 this.y = y; 30 } else { 31 System.out.println("Wrong Format"); 32 System.exit(0); 33 } 34 } 35 36 public double getX() { 37 return x; 38 } 39 40 public void setX(double x) { 41 this.x = x; 42 } 43 44 public double getY() { 45 return y; 46 } 47 48 public void setY(double y) { 49 this.y = y; 50 } 51 52 public void display() { 53 System.out.println("(" + String.format("%.2f", x) + "," + String.format("%.2f", y) + ")"); 54 } 55 56 } 57 58 59 class Line { 60 61 private Point point1; 62 private Point point2; 63 private String color; 64 65 public Line() { 66 // TODO Auto-generated constructor stub 67 } 68 69 public Line(Point p1, Point p2, String color) { 70 super(); 71 point1 = p1; 72 point2 = p2; 73 this.color = color; 74 } 75 76 public Point getPoint1() { 77 return point1; 78 } 79 80 public void setPoint1(Point point1) { 81 this.point1 = point1; 82 } 83 84 public Point getPoint2() { 85 return point2; 86 } 87 88 public void setPoint2(Point point2) { 89 this.point2 = point2; 90 } 91 92 public String getColor() { 93 return color; 94 } 95 96 public void setColor(String color) { 97 this.color = color; 98 } 99 100 public double getDistance() { 101 double distance = Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2)); 102 return Double.parseDouble(String.format("%.2f", distance)); 103 } 104 105 public void display() { 106 System.out.println("The line's color is:" + color); 107 System.out.println("The line's begin point's Coordinate is:"); 108 point1.display(); 109 System.out.println("The line's end point's Coordinate is:"); 110 point2.display(); 111 System.out.println("The line's length is:" + getDistance()); 112 } 113 114 }
二、点线面问题重构(继承与多态)
关于继承,我发现很多同学都不理解抽象类和实体类之间的关系,不知道该如何设计父类和子类,这里我借此题,仅代表我个人简略阐述我对于抽象类设计的理解。

根据本题的类图可知,本题要求Line与Point均继承抽象类Element,即Element为父类,Line与Point为子类。我们会发现,Line和Point看上去几乎毫无相似之处,该如何让它们继承同一个抽象类呢?其实,继承自同一抽象类的实体类完全可以大不相同。
首先我们需要知道抽象类的意义何在。假设没有Element这个抽象类,同时我们这边又有非常多的Point和Line,当我们想让这些Point和Line打印它们自己的信息时,我们至少需要构建两个容器ArrayList<Point>和ArrayList<Line>来存放它们,并写两个for循环来对它们进行遍历。这只是两个类,如果我们除了Point和Line以外,还有Arc、Curve等等多个类,那我们便需要新建更多的容器,写更多的for循环来遍历所有的内容,这样的工作量无疑非常巨大且重复性高。而假设我们让所有的类都继承了Element类,情况便会大大不同:我们只需要一个容器:ArrayList<Element>便可以存放所有数据,同时只需要用一个for循环遍历这个容器,并调用容器中每个Element的display()函数,Element便会将之映射到它们的子类中,并调用子类的display()实现按照预设的格式打印每个实体的信息。
由此不难看出,抽象类最大的作用便是使系统可以通过抽象类名引用子类,并可以简单快捷地通过抽象方法调用各子类中对应的方法。
那么我们该如何根据子类设计抽象类呢?说白了就是找不同。从属性到方法,功能一致的都可以作为抽象方法或者抽象类共有属性,写进抽象类,至于连实现方法都完全相同的则可以直接写进抽象类里面作为正常函数使用。就算没有一点相似也没有关系,只要把父类写成一个空抽象类就行了;继承的唯一要求便是父类中有的项目子类必须全部涵盖,对此只需要写一个空抽象类便可以作为一个万能父类使用。
而在本题中Line和Point虽然几乎没有相似处,但它们有个共同的函数:display(),这两个display()方法虽然功能相同但它们的实现方法均不相同,故只能作为抽象方法写进Element类,即“public abstract void display();”,除此之外,本题与第一题基本没有区别。
完整代码如下:
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 7 Scanner input = new Scanner(System.in); 8 9 Point p1 = new Point(input.nextDouble(), input.nextDouble()); 10 Point p2 = new Point(input.nextDouble(), input.nextDouble()); 11 12 String color = input.next(); 13 14 Line line = new Line(p1, p2, color); 15 16 Plane plane = new Plane(color); 17 18 Element element; 19 20 element = p1;//起点Point 21 element.display(); 22 23 element = p2;//终点Point 24 element.display(); 25 26 element = line;//线段 27 element.display(); 28 29 element = plane;//面 30 element.display(); 31 32 } 33 34 } 35 36 37 abstract class Element { 38 39 public Element() { 40 // TODO Auto-generated constructor stub 41 } 42 43 public abstract void display(); 44 45 } 46 47 48 class Point extends Element { 49 50 private double x; 51 private double y; 52 53 public Point() { 54 55 } 56 57 public Point(double x, double y) { 58 if (x > 0 && x <= 200 && y > 0 && y <= 200) { 59 this.x = x; 60 this.y = y; 61 } else { 62 System.out.println("Wrong Format"); 63 System.exit(0); 64 } 65 } 66 67 public double getX() { 68 return x; 69 } 70 71 public void setX(double x) { 72 this.x = x; 73 } 74 75 public double getY() { 76 return y; 77 } 78 79 public void setY(double y) { 80 this.y = y; 81 } 82 83 @Override 84 public void display() { 85 System.out.printf("(%.2f,%.2f)\n", x, y); 86 } 87 88 } 89 90 91 class Line extends Element { 92 93 private Point point1; 94 private Point point2; 95 private String color; 96 97 public Line() { 98 // TODO Auto-generated constructor stub 99 } 100 101 public Line(Point p1, Point p2, String color) { 102 super(); 103 point1 = p1; 104 point2 = p2; 105 this.color = color; 106 } 107 108 public Point getPoint1() { 109 return point1; 110 } 111 112 public void setPoint1(Point point1) { 113 this.point1 = point1; 114 } 115 116 public Point getPoint2() { 117 return point2; 118 } 119 120 public void setPoint2(Point point2) { 121 this.point2 = point2; 122 } 123 124 public String getColor() { 125 return color; 126 } 127 128 public void setColor(String color) { 129 this.color = color; 130 } 131 132 public double getDistance() { 133 return Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2)); 134 } 135 136 @Override 137 public void display() { 138 System.out.println("The line's color is:" + color); 139 System.out.println("The line's begin point's Coordinate is:"); 140 point1.display(); 141 System.out.println("The line's end point's Coordinate is:"); 142 point2.display(); 143 System.out.printf("The line's length is:%.2f\n", getDistance()); 144 } 145 146 } 147 148 149 class Plane extends Element { 150 151 private String color; 152 153 public Plane() { 154 // TODO Auto-generated constructor stub 155 } 156 157 public Plane(String color) { 158 this.color = color; 159 } 160 161 public String getColor() { 162 return color; 163 } 164 165 public void setColor(String color) { 166 this.color = color; 167 } 168 169 @Override 170 public void display() { 171 System.out.print("The Plane's color is:" + color); 172 } 173 174 }
三、点线面问题再重构(容器类)

所谓容器,其实便是同一元素的集合,如ArrayList<Interge>便是一个整型容器,作用基本等同于整型数组。容器便像是我们曾学过的C语言中的结构体数组,不过在C语言中我们通过“结构体名 结构体数组名[预设容量]”来声明结构体数组,而在Java中我们通过“ArrayList<类名> 类容器名”来声明容器。ArrayList类拥有很多附带的方法,如add、remove等等,这使得ArrayList在使用时非常方便。除此之外本题并无难点,以下便是我的源码。
1 class Main { 2 3 public static void main(String[] args) { 4 5 Scanner input = new Scanner(System.in); 6 7 GeometryObject list = new GeometryObject(); 8 9 int choice = input.nextInt(); 10 while(choice != 0) { 11 switch(choice) { 12 case 1://insert Point object into list 13 Point p = new Point(input.nextDouble(), input.nextDouble()); 14 list.add(p); 15 break; 16 case 2://insert Line object into list 17 Line line = new Line(new Point(input.nextDouble(), input.nextDouble()), new Point(input.nextDouble(), input.nextDouble()), input.next()); 18 list.add(line); 19 break; 20 case 3://insert Plane object into list 21 Plane plane = new Plane(input.next()); 22 list.add(plane); 23 break; 24 case 4://delete index - 1 object from list 25 int index = input.nextInt(); 26 list.remove(index); 27 } 28 choice = input.nextInt(); 29 } 30 for (Element each:list.getList()) { 31 each.display(); 32 } 33 } 34 35 } 36 37 38 abstract class Element { 39 40 public Element() { 41 // TODO Auto-generated constructor stub 42 } 43 44 public abstract void display(); 45 46 } 47 48 49 class Point extends Element { 50 51 private double x; 52 private double y; 53 54 public Point() { 55 56 } 57 58 public Point(double x, double y) { 59 if (x > 0 && x <= 200 && y > 0 && y <= 200) { 60 this.x = x; 61 this.y = y; 62 } else { 63 System.out.println("Wrong Format"); 64 System.exit(0); 65 } 66 } 67 68 public double getX() { 69 return x; 70 } 71 72 public void setX(double x) { 73 this.x = x; 74 } 75 76 public double getY() { 77 return y; 78 } 79 80 public void setY(double y) { 81 this.y = y; 82 } 83 84 @Override 85 public void display() { 86 System.out.printf("(%.2f,%.2f)\n", x, y); 87 } 88 89 } 90 91 92 class Line extends Element { 93 94 private Point point1; 95 private Point point2; 96 private String color; 97 98 public Line() { 99 // TODO Auto-generated constructor stub 100 } 101 102 public Line(Point p1, Point p2, String color) { 103 super(); 104 point1 = p1; 105 point2 = p2; 106 this.color = color; 107 } 108 109 public Point getPoint1() { 110 return point1; 111 } 112 113 public void setPoint1(Point point1) { 114 this.point1 = point1; 115 } 116 117 public Point getPoint2() { 118 return point2; 119 } 120 121 public void setPoint2(Point point2) { 122 this.point2 = point2; 123 } 124 125 public String getColor() { 126 return color; 127 } 128 129 public void setColor(String color) { 130 this.color = color; 131 } 132 133 public double getDistance() { 134 return Math.sqrt(Math.pow(point1.getX() - point2.getX(), 2) + Math.pow(point1.getY() - point2.getY(), 2)); 135 } 136 137 @Override 138 public void display() { 139 System.out.println("The line's color is:" + color); 140 System.out.println("The line's begin point's Coordinate is:"); 141 point1.display(); 142 System.out.println("The line's end point's Coordinate is:"); 143 point2.display(); 144 System.out.printf("The line's length is:%.2f\n", getDistance()); 145 } 146 147 } 148 149 150 class Plane extends Element { 151 152 private String color; 153 154 public Plane() { 155 // TODO Auto-generated constructor stub 156 } 157 158 public Plane(String color) { 159 this.color = color; 160 } 161 162 public String getColor() { 163 return color; 164 } 165 166 public void setColor(String color) { 167 this.color = color; 168 } 169 170 @Override 171 public void display() { 172 System.out.println("The Plane's color is:" + color); 173 } 174 175 } 176 177 178 class GeometryObject { 179 180 private ArrayList<Element> list = new ArrayList<>(); 181 182 public GeometryObject() { 183 // TODO Auto-generated constructor stub 184 } 185 186 public void add(Element e) { 187 list.add(e); 188 } 189 190 public void remove(int index) { 191 if (index <= list.size()) { 192 list.remove(index - 1); 193 } 194 } 195 196 public ArrayList<Element> getList(){ 197 return list; 198 } 199 200 }
Java实现链表
就我个人的感觉上来说,Java实现链表与C语言实现链表并无二致,无非是将C语言中的struct element{ xxx xxxxx; ……; element * next; };换成了class Node<E> { private E o; private Node<E> next; …… },因此便不作分析,仅将我的双向链表的PowerDesigner类图与源码奉上。
1 public class Main { 2 3 public static void main(String[] args) { 4 DoubleLinkedList<String> list1 = new DoubleLinkedList<>(); 5 System.out.println("\"The list1 is empty\" is " + list1.isEmpty()); 6 list1.add("第1个元素"); 7 list1.add("第2个元素"); 8 list1.add("第5个元素"); 9 list1.add("第4个元素"); 10 list1.printList(); 11 list1.add(3, "第3个元素"); 12 list1.add(6, "越界元素"); //越界数据测试(边界值) 13 list1.printList(); 14 System.out.println("列表的长度是" + list1.getSize()); 15 list1.remove(0); 16 list1.printList(); 17 list1.remove(4); //越界数据测试(边界值) 18 list1.printList(); 19 list1.add(0, "临时元素1"); //有效数据测试(边界值) 20 list1.printList(); 21 list1.add(6, "临时元素5"); //有效数据测试(边界值) 22 list1.printList(); 23 list1.remove(5); //有效数据测试(边界值) 24 list1.printList(); 25 list1.remove(1); //有效数据测试(边界值) 26 list1.printList(); 27 System.out.println("第三个元素是{" + list1.getData(3) + "}"); 28 System.out.println("第五个元素是{" + list1.getData(4) + "}"); //越界数据测试(边界值) 29 System.out.println("\"The list1 is empty\" is " + list1.isEmpty()); 30 System.out.println("列表的长度是" + list1.getSize()); 31 } 32 33 } 34 35 36 class Node<E> { 37 38 private E data;//数据域,类型为泛型E 39 40 private Node<E> next = null;//后继引用(指针) 41 42 private Node<E> previous = null;//前驱引用(指针) 43 44 public Node() { 45 46 } 47 48 public Node(E data) { 49 super(); 50 this.data = data; 51 } 52 53 public E getData() { 54 return data; 55 } 56 57 public void setData(E data) { 58 this.data = data; 59 } 60 61 public Node<E> getNext() { 62 return next; 63 } 64 65 public void setNext(Node<E> next) { 66 this.next = next; 67 } 68 69 public Node<E> getPrevious() { 70 return previous; 71 } 72 73 public void setPrevious(Node<E> previous) { 74 this.previous = previous; 75 } 76 77 } 78 79 80 interface DoubleLinkedListImpl<E> { 81 82 public boolean isEmpty(); 83 84 public int getSize(); 85 86 public E getData(int index); 87 88 public void remove(); 89 90 public void remove(int index); 91 92 public void add(int index, E theElement); 93 94 public void add(E element); 95 96 public void printList(); 97 98 public E getFirst(); 99 100 public E getLast(); 101 102 } 103 104 105 class DoubleLinkedList<E> implements DoubleLinkedListImpl<E> { 106 107 private Node<E> head;//头结点,非第一个节点 108 109 private Node<E> curr;//当前节点 110 111 private Node<E> tail;//最后一个节点 112 113 private int size; 114 115 public DoubleLinkedList() { 116 super(); 117 head = new Node<>(); 118 curr = head; 119 tail = head; 120 } 121 122 @Override 123 public boolean isEmpty() { 124 if (size == 0) { 125 return true; 126 } else { 127 return false; 128 } 129 } 130 131 @Override 132 public int getSize() { 133 return size; 134 } 135 136 @Override 137 public E getData(int index) { 138 if (index > size || index < 0) { 139 System.out.println("Index \"" + index + "\" out of list!"); 140 return null; 141 } else { 142 curr = head; 143 for (int i = 0; i < index; i ++, curr = curr.getNext()); 144 return curr.getData(); 145 } 146 } 147 148 @Override 149 public void remove() { 150 curr = tail.getPrevious(); 151 tail = curr; 152 tail.setNext(null); 153 size --; 154 } 155 156 @Override 157 public void remove(int index) { 158 if (index > size || index <= 0) { 159 System.out.println("Index \"" + index + "\" out of list!"); 160 } else { 161 if (index == size) { 162 tail = tail.getPrevious(); 163 tail.setNext(null); 164 size --; 165 } 166 else { 167 curr = head; 168 for (int i = 0; i < index - 1; i ++, curr = curr.getNext()); 169 curr.setNext(curr.getNext().getNext()); 170 curr.getNext().setPrevious(curr); 171 size --; 172 } 173 } 174 } 175 176 @Override 177 public void add(int index, E theElement) { 178 if (index > size || index <= 0) { 179 System.out.println("Index \"" + index + "\" out of list!"); 180 } else { 181 curr = head; 182 Node<E> temp = new Node<>(theElement); 183 for (int i = 0; i < index - 1; i ++, curr = curr.getNext()); 184 curr.getNext().setPrevious(temp); 185 temp.setPrevious(curr); 186 temp.setNext(curr.getNext()); 187 curr.setNext(temp); 188 size ++; 189 } 190 } 191 192 @Override 193 public void add(E element) { 194 Node<E> temp = new Node<>(element); 195 tail.setNext(temp); 196 temp.setPrevious(tail); 197 tail = temp; 198 size ++; 199 } 200 201 @Override 202 public void printList() { 203 curr = head; 204 if (curr.getNext() == null) { 205 System.out.println("The list is empty!"); 206 } else { 207 curr = head.getNext(); 208 for (int i = 0; i < size; i++, curr = curr.getNext()) { 209 if (i > 0) { 210 System.out.print(", "); 211 } 212 System.out.print("Node" + (i + 1) + "{" + curr.getData() + "}"); 213 } 214 System.out.println(); 215 } 216 } 217 218 @Override 219 public E getFirst() { 220 if (head.getNext() == null) { 221 System.out.println("The first data is null!"); 222 return null; 223 } else { 224 return head.getNext().getData(); 225 } 226 } 227 228 @Override 229 public E getLast() { 230 if (tail.getData() == null) { 231 System.out.println("The last data is null!"); 232 return null; 233 } else { 234 return tail.getData(); 235 } 236 }//当前链表节点数 237 238 }

农夫过河ver.5

一见到这张类图,想必大家都与我一样感觉头皮发麻。但事实上,我大约用了2小时便实现了代码的迭代与调试,下面我便来与大家说说我的设计思路。
一眼望去,不难发现这张类图中共有4个抽象类,分别为AbstractGame、MaterialObject、AbstractTransport和AbstractRule,这四个类和它们的子类几乎占据了类图的所有内容。射人先射马,擒贼先擒王,我们便从这4个类的子类开始着手设计。
首先是MaterialObject类,子类分别为Animal、Person和Plant;根据类图中的信息,MaterialObject拥有3个私有属性:type、place、isExist,其中type用于记录人为赋予的实体的种类名,如“羊”、“狼”等,place用于记录实体当前的位置,isExist用于记录实体的存活状态;同时MarterialObject还拥有3个方法,分别是用于更改存活状态的diedOut()、用于获取存活状态的isExist()和用于展示实体当前状态的showStatus()。在了解上述信息以后,我们便可以开始着手子类的设计。关于Animal类,它有一个私有属性recipe(食谱),和4个主要方法:eat()(吃掉其他实体)、addedToRecipe()(将实体添加至食谱)、isFood()(判断实体是否在自己的食谱中)和canBeEat()(判断实体能否被自己吃到)。前三个方法并没有什么难度,要注意的只有canBeEat(),所谓判断实体能否被吃掉,其实就是判断是否该实体与自己在河的同一侧且农夫不在场,如果是则返回true,反之返回false。由于农夫和植物均不会吃其它生物,故不需要设置上述属性。
然后是AbstractTransport类。其子类Boat拥有board()(载货上船)和disembark()(卸货下船)两个方法,实现方式便示将实体加入到父类的容器goodses(货物)中和将实体从中移除,另外需注意的是当向船上装货时,船的capacity(容量)也应当相应的减少,同时每次装货都应当检测货物与船是否在同一个地方以及船是否有足够的容量。至于crossRiver的实现方法便是改变船和所有货物的位置。
以下是我的powerDesigner类图及源码。
农夫过河ver.5
1 import java.util.ArrayList; 2 import java.util.Scanner; 3 import java.util.HashSet; 4 5 public class Main { 6 public static void main(String[] args) { 7 Game game = new Game(); 8 game.play(); 9 } 10 11 } 12 13 14 abstract class MaterialObject { 15 16 private String type; 17 private String place; 18 private boolean crossed = false; 19 private boolean isExist = false; 20 21 public MaterialObject() { 22 23 } 24 25 public void diedOut() { 26 isExist = true; 27 } 28 29 public boolean isExist() { 30 return isExist; 31 } 32 33 public void showStatus() { 34 System.out.println(type + " is alive\t:" + (!isExist) + "\t"+ type + " has cross\t:" + crossed); 35 } 36 37 @Override 38 public boolean equals(Object obj) { 39 MaterialObject m = (MaterialObject) obj; 40 if (m.type.equals(type)) { 41 return true; 42 } else { 43 return false; 44 } 45 } 46 47 public String getType() { 48 return type; 49 } 50 51 public void setType(String type) { 52 this.type = type; 53 } 54 55 public String getPlace() { 56 return place; 57 } 58 59 public void setPlace(String place) { 60 this.place = place; 61 } 62 63 public boolean isCrossed() { 64 return crossed; 65 } 66 67 public void setCrossed(boolean crossed) { 68 this.crossed = crossed; 69 } 70 71 public void setExist(boolean isExist) { 72 this.isExist = isExist; 73 } 74 75 } 76 77 78 class Animal extends MaterialObject { 79 80 private HashSet<MaterialObject> recipe; 81 82 public Animal(String type) { 83 super.setType(type); 84 recipe = new HashSet<>(); 85 } 86 87 public boolean eat(MaterialObject m) { 88 m.diedOut(); 89 return true; 90 } 91 92 public void addedToRecipe(MaterialObject m) { 93 recipe.add(m); 94 } 95 96 public boolean isFood(MaterialObject m) { 97 for (MaterialObject each:recipe) { 98 if (each.equals(m)) { 99 return true; 100 } 101 } 102 return false; 103 } 104 105 public boolean canBeEat(MaterialObject m) { 106 if (isFood(m) && (super.isCrossed() == m.isCrossed()) && GameData.farmer.isCrossed() != isCrossed()) { 107 return true; 108 } else { 109 return false; 110 } 111 } 112 113 } 114 115 116 class Person extends MaterialObject { 117 118 public Person(String type) { 119 super.setType(type); 120 } 121 122 } 123 124 125 class Plant extends MaterialObject { 126 127 public Plant(String type) { 128 super.setType(type); 129 } 130 131 } 132 133 134 abstract class AbstracTransport { 135 136 private String place; 137 private int capacity; 138 private boolean crossed; 139 private ArrayList<MaterialObject> goodses = new ArrayList<>(); 140 141 public AbstracTransport() { 142 143 } 144 145 public void moveTo(String destination) { 146 place = destination; 147 for (MaterialObject each:goodses) { 148 each.setPlace(destination); 149 } 150 } 151 152 public String getPlace() { 153 return place; 154 } 155 156 public void setPlace(String place) { 157 this.place = place; 158 } 159 160 public int getCapacity() { 161 return capacity; 162 } 163 164 public void setCapacity(int capacity) { 165 this.capacity = capacity; 166 } 167 168 public ArrayList<MaterialObject> getGoodses() { 169 return goodses; 170 } 171 172 public void setGoodses(ArrayList<MaterialObject> goodses) { 173 this.goodses = goodses; 174 } 175 176 public boolean isCrossed() { 177 return crossed; 178 } 179 180 public void setCrossed(boolean crossed) { 181 this.crossed = crossed; 182 } 183 184 } 185 186 187 class Boat extends AbstracTransport { 188 189 public Boat(int capacity) { 190 super.setCapacity(capacity); 191 } 192 193 public void crossRiver() { 194 GameData.farmer.setCrossed(!GameData.farmer.isCrossed()); 195 super.setCrossed(!super.isCrossed()); 196 for (MaterialObject each:super.getGoodses()) { 197 each.setCrossed(!each.isCrossed()); 198 } 199 } 200 201 public void board(MaterialObject m) { 202 if (super.isCrossed() == m.isCrossed()) { 203 if (super.getCapacity() > 0) { 204 super.getGoodses().add(m); 205 super.setCapacity(super.getCapacity() - 1); 206 } else { 207 System.out.println("The boat is full!"); 208 } 209 } else { 210 System.out.println("The " + m.getType() + " and the boat are not on the same side!"); 211 } 212 213 } 214 215 public void disembark(MaterialObject m) { 216 if (!super.getGoodses().remove(m)) { 217 System.out.println("The " + m.getType() + " is not on the boat"); 218 } 219 super.setCapacity(super.getCapacity() + 1); 220 } 221 222 } 223 224 225 abstract class AbstractRule { 226 227 public AbstractRule() { 228 // TODO Auto-generated constructor stub 229 } 230 231 public abstract boolean judge(); 232 233 } 234 235 236 class GameSuccessRule extends AbstractRule{ 237 238 private CrossRiverRule crossRiverRule; 239 private ObjectExistRule objectExistRule; 240 241 public GameSuccessRule(CrossRiverRule crossRiverRule, ObjectExistRule objectExistRule) { 242 super(); 243 this.crossRiverRule = crossRiverRule; 244 this.objectExistRule = objectExistRule; 245 } 246 247 @Override 248 public boolean judge() { 249 return !objectExistRule.judge() && crossRiverRule.judge(); 250 } 251 252 } 253 254 255 class GameOverRule extends AbstractRule{ 256 257 private ObjectExistRule objectExistRule; 258 259 public GameOverRule(ObjectExistRule objectExistRule) { 260 super(); 261 this.objectExistRule = objectExistRule; 262 } 263 264 @Override 265 public boolean judge() { 266 return objectExistRule.judge(); 267 } 268 269 } 270 271 272 class ObjectExistRule extends AbstractRule{ 273 274 private GameData gameData; 275 276 public ObjectExistRule(GameData gameData) { 277 this.gameData = gameData; 278 } 279 280 @Override 281 public boolean judge() { 282 for (MaterialObject each:gameData.getObjects()) { 283 if (each.isExist()) { 284 return true; 285 } 286 } 287 return false; 288 } 289 290 } 291 292 293 class CrossRiverRule extends AbstractRule{ 294 295 private GameData gameData; 296 297 public CrossRiverRule(GameData gameData) { 298 this.gameData = gameData; 299 } 300 301 @Override 302 public boolean judge() { 303 for (MaterialObject each:gameData.getObjects()) { 304 if (!each.isCrossed()) { 305 return false; 306 } 307 } 308 return true; 309 } 310 311 public boolean hasCross(MaterialObject m) { 312 return m.isCrossed(); 313 } 314 315 public GameData getGameData() { 316 return gameData; 317 } 318 319 public void setGameData(GameData gameData) { 320 this.gameData = gameData; 321 } 322 323 } 324 325 326 class GameUI { 327 328 public void menu() { 329 /* 显示菜单 */ 330 System.out.println("==================Please choose operation============"); 331 System.out.println("\t==========1:Cross the river alone==========="); 332 System.out.println("\t==========2:Cross the river with wolf========="); 333 System.out.println("\t==========3:Cross the river with sheep============"); 334 System.out.println("\t==========4:Cross the river with cabbage=========="); 335 System.out.println("\t==========0:Quit==============="); 336 System.out.println("==================================================="); 337 System.out.println("Input the number(0~4):"); 338 } 339 340 public void showStatus(GameData gameData) { 341 for (MaterialObject each:gameData.getObjects()) { 342 each.showStatus(); 343 } 344 } 345 346 } 347 348 349 class GameData { 350 351 public static Person farmer = new Person("farmer"); 352 353 private Animal wolf; 354 private Animal sheep; 355 private Plant cabbage; 356 private Boat boat; 357 private ArrayList<MaterialObject> objects; 358 359 public GameData() { 360 wolf = new Animal("wolf"); 361 sheep = new Animal("sheep"); 362 cabbage = new Plant("cabbage"); 363 boat = new Boat(1); 364 365 wolf.addedToRecipe(sheep); 366 sheep.addedToRecipe(cabbage); 367 objects = new ArrayList<>() { 368 { 369 add(wolf); 370 add(sheep); 371 add(cabbage); 372 add(farmer); 373 } 374 }; 375 } 376 377 public Animal getWolf() { 378 return wolf; 379 } 380 381 public void setWolf(Animal wolf) { 382 this.wolf = wolf; 383 } 384 385 public Animal getSheep() { 386 return sheep; 387 } 388 389 public void setSheep(Animal sheep) { 390 this.sheep = sheep; 391 } 392 393 public Plant getCabbage() { 394 return cabbage; 395 } 396 397 public void setCabbage(Plant cabbage) { 398 this.cabbage = cabbage; 399 } 400 401 public Boat getBoat() { 402 return boat; 403 } 404 405 public void setBoat(Boat boat) { 406 this.boat = boat; 407 } 408 409 public ArrayList<MaterialObject> getObjects() { 410 return objects; 411 } 412 413 public void setObjects(ArrayList<MaterialObject> objects) { 414 this.objects = objects; 415 } 416 417 } 418 419 420 abstract class AbstractGame { 421 422 private AbstractRule gameOverRule; 423 private AbstractRule gameSuccesRule; 424 private GameData gameData; 425 426 public AbstractGame() { 427 // TODO Auto-generated constructor stub 428 } 429 430 public abstract void play(); 431 432 public AbstractRule getGameOverRule() { 433 return gameOverRule; 434 } 435 436 public void setGameOverRule(AbstractRule gameOverRule) { 437 this.gameOverRule = gameOverRule; 438 } 439 440 public AbstractRule getGameSuccesRule() { 441 return gameSuccesRule; 442 } 443 444 public void setGameSuccesRule(AbstractRule gameSuccesRule) { 445 this.gameSuccesRule = gameSuccesRule; 446 } 447 448 public GameData getGameData() { 449 return gameData; 450 } 451 452 public void setGameData(GameData gameDate) { 453 this.gameData = gameDate; 454 } 455 456 } 457 458 459 class Game extends AbstractGame{ 460 461 private GameUI gui; 462 463 public Game() { 464 gui = new GameUI(); 465 super.setGameData(new GameData()); 466 super.setGameOverRule(new GameOverRule(new ObjectExistRule(super.getGameData()))); 467 super.setGameSuccesRule(new GameSuccessRule(new CrossRiverRule(super.getGameData()), new ObjectExistRule(super.getGameData()))); 468 } 469 470 public void play() { 471 472 Scanner input = new Scanner(System.in); 473 while(!super.getGameOverRule().judge()) { 474 gui.menu(); 475 char choice = input.next().charAt(0);//用户输入选择 476 switch(choice) { 477 case '0': 478 System.out.println("game over!"); 479 break; 480 case '1':/* 农夫独自过河的处理 */ 481 super.getGameData().getBoat().crossRiver(); 482 break; 483 case '2':/* 农夫带狼的处理 */ 484 super.getGameData().getBoat().board(super.getGameData().getWolf()); 485 super.getGameData().getBoat().crossRiver(); 486 super.getGameData().getBoat().disembark(super.getGameData().getWolf()); 487 break; 488 case '3':/* 农夫带羊的处理 */ 489 super.getGameData().getBoat().board(super.getGameData().getSheep()); 490 super.getGameData().getBoat().crossRiver(); 491 super.getGameData().getBoat().disembark(super.getGameData().getSheep()); 492 break; 493 case '4':/* 农夫带白菜的处理 */ 494 super.getGameData().getBoat().board(super.getGameData().getCabbage()); 495 super.getGameData().getBoat().crossRiver(); 496 super.getGameData().getBoat().disembark(super.getGameData().getCabbage()); 497 break; 498 default: 499 System.out.println("This command is no found!"); 500 } 501 if (super.getGameData().getSheep().canBeEat(super.getGameData().getCabbage())) { 502 super.getGameData().getSheep().eat(super.getGameData().getCabbage()); 503 } 504 if (super.getGameData().getWolf().canBeEat(super.getGameData().getSheep())) { 505 super.getGameData().getWolf().eat(super.getGameData().getSheep()); 506 } 507 gui.showStatus(super.getGameData()); 508 if (super.getGameSuccesRule().judge()) { 509 System.out.println("game over: you win !"); 510 break; 511 } else if (super.getGameOverRule().judge()) { 512 System.out.println("game over: you lose !"); 513 break; 514 } 515 } 516 input.close(); 517 518 } 519 520 }
总结:
经过这四周的学习,我已经熟练掌握了继承与多态、对象容器等的用法,并对Java类设计有了一定的认识和见解。关于近几周的学习情况,或许是封校使我懈怠了许多,对此我还需要进一步端正学习态度。以上便是本篇博客的全部内容,感谢阅读。
posted on 2022-05-01 23:36 AQHuiguang 阅读(5) 评论(0) 收藏 举报
浙公网安备 33010602011771号