提交 034893b7 编写于 作者: Y Yuan Yuan

上传任务1和2

上级 c11e2447
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "charac.md", "source": "charac.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "c2f6aa1cf9794d3a8a1c43b7c5375151" "exercise_id": "c2f6aa1cf9794d3a8a1c43b7c5375151"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "feature.md", "source": "feature.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "d2541f9f1c344043882ebbe75a98b71f" "exercise_id": "d2541f9f1c344043882ebbe75a98b71f"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "concept.md", "source": "concept.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "b3d0d1b514ee409b9e2924ee20a16407" "exercise_id": "b3d0d1b514ee409b9e2924ee20a16407"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "names.md", "source": "names.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "2fb5e237ed284e599eaa5203c538d449" "exercise_id": "2fb5e237ed284e599eaa5203c538d449"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "instance.md", "source": "instance.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "6355a3c2bf00436f854f34094c9e33b6" "exercise_id": "6355a3c2bf00436f854f34094c9e33b6"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "encapsulation.md", "source": "encapsulation.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "d2c7dabb04e54f0d9863e2b4bdd67339" "exercise_id": "d2c7dabb04e54f0d9863e2b4bdd67339"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "access.md", "source": "access.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "0fadf6ba49ce4b828b2481168592359a" "exercise_id": "0fadf6ba49ce4b828b2481168592359a"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "choice.md", "source": "choice.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "795a27d3a46b4975baee3103fd2952d8" "exercise_id": "795a27d3a46b4975baee3103fd2952d8"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "using.md", "source": "using.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "feeb96d62e6a4970b46fb4891c886f71" "exercise_id": "feeb96d62e6a4970b46fb4891c886f71"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "identify.md", "source": "identify.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "4f751c7e9f604a15bfa3a7956039e42e" "exercise_id": "4f751c7e9f604a15bfa3a7956039e42e"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "getcls.md", "source": "getcls.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "65dad5a0812341f7affad7a7d8f2cfc5" "exercise_id": "65dad5a0812341f7affad7a7d8f2cfc5"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "rm.md", "source": "rm.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "e72f3c5991444fb784caba8f2859e8ab" "exercise_id": "e72f3c5991444fb784caba8f2859e8ab"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "method.md", "source": "method.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "45e7f995c1184a51881a7d263ad13bc8" "exercise_id": "45e7f995c1184a51881a7d263ad13bc8"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "variability.md", "source": "variability.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "6e798fb4d3084e069b89031c74fdd525" "exercise_id": "6e798fb4d3084e069b89031c74fdd525"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "observability.md", "source": "observability.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "42bda5aa3190433a85d3ef55988c6cd5" "exercise_id": "42bda5aa3190433a85d3ef55988c6cd5"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "tolerance.md", "source": "tolerance.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "a31e656b0e94482296aeb7daa08b0803" "exercise_id": "a31e656b0e94482296aeb7daa08b0803"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "principle.md", "source": "principle.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "0eed98f392134f78ac8895009a5a6d14" "exercise_id": "0eed98f392134f78ac8895009a5a6d14"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "singleton.md", "source": "singleton.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "d569e6c196d645b5830df66b3e073ab1" "exercise_id": "d569e6c196d645b5830df66b3e073ab1"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "prototype.md", "source": "prototype.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "4741d847840e4133a6306dc3ff5fc004" "exercise_id": "4741d847840e4133a6306dc3ff5fc004"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "conn.md", "source": "conn.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "ea16c59ff6bb442f8f60ac817c416c9b" "exercise_id": "ea16c59ff6bb442f8f60ac817c416c9b"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "regular.md", "source": "regular.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "2b732ec63d934143964a669adfd239d0" "exercise_id": "2b732ec63d934143964a669adfd239d0"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "compare1.md", "source": "compare1.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "a54c8f131d9f4e80893ae9badecb6fe6" "exercise_id": "a54c8f131d9f4e80893ae9badecb6fe6"
......
{ {
"type": "code_options", "type": "code_options",
"author": null, "author": "Yuan",
"source": "compare2.md", "source": "compare2.md",
"notebook_enable": false, "notebook_enable": false,
"exercise_id": "fc3ca0907cb640d7bb5eb6cc88974a1c" "exercise_id": "fc3ca0907cb640d7bb5eb6cc88974a1c"
......
{
"node_id": "oo-e001f9dfe2da4caabaec2a1f75eb5bb3",
"keywords": [],
"children": [],
"export": [
"exercise_pre.json",
"exercise_1.json",
"exercise_2.json",
"exercise_3.json",
"exercise_4.json",
"exercise_10.json",
"exercise_11.json",
"exercise_5.json",
"exercise_8.json",
"exercise_9.json",
"exercise_12.json",
"exercise_6.json",
"exercise_7.json"
],
"keywords_must": [],
"keywords_forbid": [],
"group": 0
}
\ No newline at end of file
{
"type": "code_options",
"author": null,
"source": "exercise_1.md",
"notebook_enable": false,
"exercise_id": "f8923895ff074f8888b3ba208e15b8d3"
}
\ No newline at end of file
# 题目1
#### 题目1
创建一个Book类,Book类的属性如下:
| 属性名 | 类型 | 说明 |
| ----------- | -------- | ------------ |
| id | int | 书的id |
| bookName | String | 书名 |
| type | BookType | 书的类型 |
| borrowTimes | int | 书的借阅次数 |
| pages | int | 书的页码 |
| price | double | 书的价格 |
注意:这些属性都是private权限
## 答案
```java
public class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_10.md",
"notebook_enable": false,
"exercise_id": "37f75007dd1c430583ae28c5f537c097"
}
\ No newline at end of file
# 题目10
定义一个新的类OperatingSystemBook,这个类继承自Book类,实现构造方法`public OperatingSystemBook(int id, String bookName, BookType type, int pages, double price);`,完成和父类Book相同的构造方法。
同时并实现一个`public void printBookName();`方法,作用是打印"This is xxx",其中xxx是书名(打印需要带换行符)。
提示:推荐使用`System.out.println()`来实现打印。
## 答案
```java
public class OperatingSystemBook extends Book {
public OperatingSystemBook(int id, String bookName, BookType type, int pages, double price) {
super(id, bookName, type, pages, price);
}
public void printBookName() {
System.out.println("This is " + getBookName());
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_11.md",
"notebook_enable": false,
"exercise_id": "25cb118c94064c0d827cbe1b0ee21453"
}
\ No newline at end of file
# 题目11
Book类的对象都有id属性,对于id的管理,在每次新建对象的时候手动输入id显然是极为麻烦的,而且会出现id重复的可能。
因此,我们需要实现一个类来帮助管理id,请创建一个IDHolder类,类的属性如下:
| 属性名 | 类型 | 说明 |
| ------ | ---- | ------------ |
| id | int | 当前分配的id |
注意:id为private权限,id为静态变量。
## 答案
```java
public class IDHolder {
private static int id = 1;
}
```
## 选项
## 补充
请思考将id设置成静态变量的原因。
{
"type": "code_options",
"author": null,
"source": "exercise_12.md",
"notebook_enable": false,
"exercise_id": "438930f965764e938748249f479c4aaf"
}
\ No newline at end of file
# 题目12
在IDHolder类中,实现一个`public static int fetchId();`,返回当前分配的id,并将id属性的值加一。
## 答案
```java
public class IDHolder {
private static int id = 1;
public static int fetchId() {
return id++;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_2.md",
"notebook_enable": false,
"exercise_id": "6d1b3337ee784f41a73b8c008f8d0c15"
}
\ No newline at end of file
# 题目2
在Book类中,实现下列方法:
+ `public int getId();`方法,作用是获取id属性;
+ `public String getBookName();`方法,作用是获取bookName属性;
+ `public BookType getBookType();`方法,作用是获取bookType属性;
+ `public int getBorrowTimes();`方法,作用是获取borrowTimes属性;
+ `public int getPages();`方法,作用是获取pages属性;
+ `public double getPrice();`方法,作用是获取price属性。
## 答案
```java
public class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
public int getId() {
return id;
}
public String getBookName() {
return bookName;
}
public BookType getBookType() {
return type;
}
public int getBorrowTimes() {
return borrowTimes;
}
public int getPages() {
return pages;
}
public double getPrice() {
return price;
}
}
```
## 选项
## 补充
这类方法,在Java中,我们一般称之为Getter方法,作用是对外提供访问类的私有属性的接口。
在IDEA中,在Code-Generate中可以一键生成Getter方法。
{
"type": "code_options",
"author": null,
"source": "exercise_3.md",
"notebook_enable": false,
"exercise_id": "951b055ad89f49c78d3ed7fbfeb166ac"
}
\ No newline at end of file
# 题目3
实现一个方法`public Book(int id, String bookName, BookType type, int pages, double price);`,作用是使用方法中的参数初始化对象的属性,注意参数没有borrowTimes属性,对象的borrowTimes属性直接设置成0。
提示:如果担心id冲突,可以使用`this.id=id;`这样的写法,this代表对象本身
## 答案
```java
public class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.pages = pages;
this.price = price;
this.borrowTimes = 0;
}
public int getId() {
return id;
}
public String getBookName() {
return bookName;
}
public BookType getBookType() {
return type;
}
public int getBorrowTimes() {
return borrowTimes;
}
public int getPages() {
return pages;
}
public double getPrice() {
return price;
}
}
```
## 选项
## 补充
这类方法,在Java中,我们一般称之为**构造方法**,这类方法的前面没有public/private这样的关键字,**方法名也只能是类名**,在新建一个该类的对象时会自动调用该方法完成对对象的初始化。
{
"type": "code_options",
"author": null,
"source": "exercise_4.md",
"notebook_enable": false,
"exercise_id": "58a14cb1298e4e1993f6f2502c21c706"
}
\ No newline at end of file
# 题目4
再定义一个构造方法`public Book();`,作用是:
+ 将id设置成1
+ bookName设置成"BUAAOO"
+ type设置成BookType.ObjectOrientedBook
+ borrowTimes设置成0
+ pages设置成100
+ price设置成50.0
## 答案
```java
public class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.pages = pages;
this.price = price;
this.borrowTimes = 0;
}
public Book() {
this.id = 1;
this.bookName = "BUAAOO";
this.type = BookType.ObjectOrientedBook;
this.pages = 100;
this.price = 50.0;
this.borrowTimes = 0;
}
public int getId() {
return id;
}
public String getBookName() {
return bookName;
}
public BookType getBookType() {
return type;
}
public int getBorrowTimes() {
return borrowTimes;
}
public int getPages() {
return pages;
}
public double getPrice() {
return price;
}
}
```
## 选项
## 补充
在实现这个方法的时候,并不用将题目3中的方法删除,**他们并不冲突**
这是因为这两个方法虽然有着相同的名字,但他们的参数不同,所以导致这两个方法其实是可以共存的。这种现象在Java中称为**重载(Overloading)**
{
"type": "code_options",
"author": null,
"source": "exercise_5.md",
"notebook_enable": false,
"exercise_id": "de97e9a9e419494f8b8874051c93079b"
}
\ No newline at end of file
# 题目5
Book类的工作已经告一段落了,由于要实现一些Book的子类,现在将Book类改写为一个抽象类。
## 答案
```java
public abstract class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.pages = pages;
this.price = price;
this.borrowTimes = 0;
}
public Book() {
this.id = 1;
this.bookName = "BUAAOO";
this.type = BookType.ObjectOrientedBook;
this.pages = 100;
this.price = 50.0;
this.borrowTimes = 0;
}
public int getId() {
return id;
}
public String getBookName() {
return bookName;
}
public BookType getBookType() {
return type;
}
public int getBorrowTimes() {
return borrowTimes;
}
public int getPages() {
return pages;
}
public double getPrice() {
return price;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_6.md",
"notebook_enable": false,
"exercise_id": "62514c7ae51443c39a636ed8f87ab1e2"
}
\ No newline at end of file
# 题目6
定义一个新的类DataBaseBook,这个类**继承**自Book类。
## 答案
```java
public class DataBaseBook extends Book {
}
```
## 选项
## 补充
仅仅新建这个类是不够的,因为没有重写(Overwrite)父类的构造方法,因此,在题目7中,我们需要重写父类的构造方法,这样才能算成功新建一个类。
{
"type": "code_options",
"author": null,
"source": "exercise_7.md",
"notebook_enable": false,
"exercise_id": "75d51d12e2c04154b715b8751f388150"
}
\ No newline at end of file
# 题目7
在JavaBook类中,实现一个构造方法`public DataBaseBook(int id, String bookName, BookType type, int pages, double price);`,完成和父类Book相同的构造方法。
提示:super关键字
## 答案
```java
public class DataBaseBook extends Book {
super(id, bookName, type, pages, price);
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_8.md",
"notebook_enable": false,
"exercise_id": "142400cf923c4306aa5d1231177b55ff"
}
\ No newline at end of file
# 题目8
定义一个新的类ObjectOrientedBook,这个类继承自Book类,ObjectOrientedBook类还具有如下属性
| 属性名 | 类型 | 说明 |
| ----------- | ------- | ------------ |
| recommended | boolean | 书是否被推荐 |
注意:该属性为private权限。
## 答案
```java
public class ObjectOrientedBook extends Book {
private boolean recommended;
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_9.md",
"notebook_enable": false,
"exercise_id": "6013e303ca8147269aa4659c743e1303"
}
\ No newline at end of file
# 题目9
在ObjectOrientedBook类中,实现一个构造方法`public ObjectOrientedBook(String bookName, BookType type, int pages, double price, boolean recommended);`,方法的作用是在父类相同的构造方法的基础上,同时实现将recommended属性设置成参数中recommended的值。
## 答案
```java
public class ObjectOrientedBook extends Book {
private boolean recommended;
public ObjectOrientedBook(String bookName, BookType type, int pages, double price, boolean recommended) {
super(bookName, type, pages, price);
this.recommended = recommended;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_pre.md",
"notebook_enable": false,
"exercise_id": "30ff3dc3fba849eb9c794f576559b94a"
}
\ No newline at end of file
# OO技能树-1, 目标是了解创建对象的流程和工厂模式。
# 题目 pre
创建一个枚举类BookType,里面包含ObjectOrientedBook, DataBaseBook, OperatingSystemBook三个书的类型。
## 答案
```java
public enum BookType {
ObjectOrientedBook,
DataBaseBook,
OperatingSystemBook
}
```
## 选项
{
"node_id": "oo-fbc8f6f1cd754850afe77bc2c0aa94af",
"keywords": [],
"children": [],
"export": [
"exercise_14.json",
"exercise_15.json",
"exercise_16.json",
"exercise_17.json",
"exercise_13.json"
],
"keywords_must": [],
"keywords_forbid": [],
"group": 0
}
\ No newline at end of file
{
"type": "code_options",
"author": null,
"source": "exercise_13.md",
"notebook_enable": false,
"exercise_id": "5c7c56fa09224e07bbaa84ad72a0ad7f"
}
\ No newline at end of file
# 题目13
在有了三个Book的子类后,我们可以考虑创建这些类的对象了。
在创建对象时,可以直接创建,但一种更加优雅的方式是新建一个类,专门负责创建这些类的对象。
请创建一个BookSeller类。
## 答案
```java
public class BookSeller {
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_14.md",
"notebook_enable": false,
"exercise_id": "cb192461709746dd8013e3e19f46256d"
}
\ No newline at end of file
# 题目14
在BookSeller类中实现`public Book createBook(String name, String type);`方法,作用是当type等于"DB"时,创建一个DataBaseBook对象,对象的id是由IDHolder分配的id,name是参数的name,type是该类对应的枚举对象,pages为200,price为50.0。
## 答案
```java
public class BookSeller {
public Book createBook(String name, String type) {
if (type.equals("DB")) {
return new DataBaseBook(IDHolder.fetchId(), name, BookType.DataBaseBook, 200, 50.0);
}
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_15.md",
"notebook_enable": false,
"exercise_id": "50888eb4f85d4b32a6e2c9a8b0065c69"
}
\ No newline at end of file
# 题目15
在题目14的方法中迭代开发,实现当type等于"OO"时,创建一个ObjectOriented对象,对象的id是由IDHolder分配的id,name是参数的name,type是该类对应的枚举对象,pages为500,price为88.8,recommended为true。
## 答案
```java
public class BookSeller {
public Book createBook(String name, String type) {
if (type.equals("DB")) {
return new DataBaseBook(IDHolder.fetchId(), name, BookType.DataBaseBook, 200, 50.0);
}
else if (type.equals("OO")) {
return new ObjectOrientedBook(IDHolder.fetchId(), name, BookType.ObjectOrientedBook, 500, 88.8, true);
}
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_16.md",
"notebook_enable": false,
"exercise_id": "26de3f80bad24fa7af1a709d34635780"
}
\ No newline at end of file
# 题目16
在题目15的方法中迭代开发,实现当type等于"OS"时,创建一个OperatingSystemBook对象,对象的id是由IDHolder分配的id,name是参数的name,type是该类对应的枚举对象,pages为100,price为100。
## 答案
```java
public class BookSeller {
public Book createBook(String name, String type) {
if (type.equals("DB")) {
return new DataBaseBook(IDHolder.fetchId(), name, BookType.DataBaseBook, 200, 50.0);
}
else if (type.equals("OO")) {
return new ObjectOrientedBook(IDHolder.fetchId(), name, BookType.ObjectOrientedBook, 500, 88.8, true);
}
else if (type.equals("OS")) {
return new OperatingSystemBook(IDHolder.fetchId(), name, BookType.OperatingSystemBook, 100, 100);
}
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_17.md",
"notebook_enable": false,
"exercise_id": "fa42a035970944d981cf5d8d62825c6c"
}
\ No newline at end of file
# 题目17
还需要考虑的一个情况是type不满足上述的三种情况,这个时候需要返回null,代表创建了空对象。
## 答案
```java
public class BookSeller {
public Book createBook(String name, String type) {
if (type.equals("DB")) {
return new DataBaseBook(IDHolder.fetchId(), name, BookType.DataBaseBook, 200, 50.0);
}
else if (type.equals("OO")) {
return new ObjectOrientedBook(IDHolder.fetchId(), name, BookType.ObjectOrientedBook, 500, 88.8, true);
}
else if (type.equals("OS")) {
return new OperatingSystemBook(IDHolder.fetchId(), name, BookType.OperatingSystemBook, 100, 100);
}
return null;
}
}
```
## 选项
{
"node_id": "oo-a86e2abd5f014ba08eacff1faafdc338",
"keywords": [],
"children": [],
"export": [
"summary.json"
],
"keywords_must": [],
"keywords_forbid": [],
"group": 0
}
\ No newline at end of file
{
"type": "code_options",
"author": null,
"source": "summary.md",
"notebook_enable": false,
"exercise_id": "453485ce7c864b2c82025deb28c6856a"
}
\ No newline at end of file
# 总结
至此,本部分的技能树就告一段落了,我们实现的BookSeller其实是Java中的一个设计模式——工厂模式。
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个**共同的接口**来指向新创建的对象,大大减小了代码冗余的情况。
这类设计模式具有如下优点:
+ 因为调用创建方法的对象只需要传递type参数,因此调用者只需要提供type参数就行,不需要知道创建的具体细节。
+ 扩展性高,如果想增加新的创建逻辑,只需要在工厂类中新增就行。
# 思考题
思考使用工厂模式创建对象和直接实现创建对象的区别。当只有一个方法需要创建对象时?当有多个方法需要创建对象时?
# 课下任务
了解抽象工厂模式。
## 答案
## 选项
{
"node_id": "oo-bbd848aed67045f3ab960fc67217edbd",
"keywords": [],
"keywords_must": [],
"keywords_forbid": [],
"group": 0
}
\ No newline at end of file
{
"node_id": "oo-695375b6a7e1429486791ca169d82219",
"keywords": [],
"children": [],
"export": [
"exercise_1.json",
"exercise_14.json",
"exercise_4.json",
"exercise_10.json",
"exercise_11.json",
"exercise_15.json",
"exercise_5.json",
"exercise_8.json",
"exercise_9.json",
"exercise_12.json",
"exercise_2.json",
"exercise_16.json",
"exercise_6.json",
"exercise_17.json",
"exercise_7.json",
"exercise_13.json",
"exercise_3.json"
],
"keywords_must": [],
"keywords_forbid": [],
"group": 0
}
\ No newline at end of file
{
"type": "code_options",
"author": null,
"source": "exercise_1.md",
"notebook_enable": false,
"exercise_id": "a8efeb5ca6974e168041692c80af0be1"
}
\ No newline at end of file
# OO技能树-2, 目标是了解Java中的几种容器和容器的访问方法。
# 题目1
我们在上一道大题的基础上继续开发,初步完成图书管理系统的框架。
Book类需要一个书架来储存,因此我们新建一个BookShelf类,包含如下属性:
| 属性名 | 属性类别 | 说明 |
| ------ | ------------ | -------------------- |
| shelf | List\<Book\> | 管理书的列表 |
| type | BookType | 书架中存放的书的种类 |
注意:这些属性都是private权限。
## 答案
```java
import java.util.List;
public class BookShelf {
private List<Book> shelf;
private BookType type;
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_10.md",
"notebook_enable": false,
"exercise_id": "b1f02be1818c4dcbb5b6f374e27871ed"
}
\ No newline at end of file
# 题目10
在Student类的属性中新增下列属性:
| 属性名 | 属性类别 | 说明 |
| ------- | -------------- | ---------------------------- |
| manager | LibraryManager | 学生引用的LibraryManager对象 |
注意:属性是private权限。
## 答案
```java
public abstract class Student {
private int id;
private String name;
private int booksBorrowed;
private int age;
private LibraryManager manager;
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_11.md",
"notebook_enable": false,
"exercise_id": "bfbaa880c59845f688798f9cfb55743f"
}
\ No newline at end of file
# 题目11
在Student类中新增构造方法`public Student(String name, int age, LibraryManager manager);`,该方法的作用是
+ 使用IDHolder获取id
+ 将属性name设置成参数name
+ 将属性age设置成参数age
+ 将booksBorrowed设置为0
+ 将manager设置为参数manager
## 答案
```java
public abstract class Student {
private int id;
private String name;
private int booksBorrowed;
private int age;
private LibraryManager manager;
public Student(String name, int age, LibraryManager manager) {
this.id = IDHolder.fetchStuId();
this.name = name;
this.age = age;
this.booksBorrowed = 0;
this.manager = manager;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_12.md",
"notebook_enable": false,
"exercise_id": "49f1bf952cac422780e1dfca9e570e6e"
}
\ No newline at end of file
# 题目12
在LibraryManager类中实现`public Book getBook(String name, BookType type);`方法,作用是获取属性为type的书架中,名字为name的书。
## 答案
```java
public class LibraryManager {
private Map<BookType, BookShelf> lib;
private List<Student> students;
public LibraryManager() {
lib = new HashMap<>();
students = new ArrayList<>();
}
public Book getBook(String name, BookType type) {
BookShelf shelf = lib.get(type);
return shelf.getBook(name);
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_13.md",
"notebook_enable": false,
"exercise_id": "f559eeaafb704b5caf7b4f1698bec711"
}
\ No newline at end of file
# 题目13
在Book类中添加下列属性:
| 属性名 | 属性类别 | 说明 |
| --------- | -------- | -------------- |
| available | boolean | 该书是否被借阅 |
并在构造方法中增加相关内容,此时该属性应该设置为true。
注意:属性是private权限。
## 答案
```java
public abstract class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
private boolean available;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.borrowTimes = 0;
this.pages = pages;
this.price = price;
this.available = true;
}
}
```
## 选项
## 补充
这里初步体现出了继承的一个优点:即有新增的属性只用在父类中新增即可,不用在每个子类中新增,可扩展性强。
{
"type": "code_options",
"author": null,
"source": "exercise_14.md",
"notebook_enable": false,
"exercise_id": "00310543741349ddb2ef577bb26a21ac"
}
\ No newline at end of file
# 题目14
在Book类中实现`public void borrowed();`方法,作用是修改借阅状态,表示这本书已经被借阅,同时将这本书的借阅次数加一。
## 答案
```java
public abstract class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
private boolean available;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.borrowTimes = 0;
this.pages = pages;
this.price = price;
this.available = true;
}
public void borrowed() {
this.available = false;
borrowTimes++;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_15.md",
"notebook_enable": false,
"exercise_id": "ff7325af40a24b2fba710b56c31bb716"
}
\ No newline at end of file
# 题目15
在Book类中实现`public void returned();`方法,作用是修改借阅状态,表示这本书已经被归还。
## 答案
```java
public abstract class Book {
private int id;
private String bookName;
private BookType type;
private int borrowTimes;
private int pages;
private double price;
private boolean available;
public Book(int id, String bookName, BookType type, int pages, double price) {
this.id = id;
this.bookName = bookName;
this.type = type;
this.borrowTimes = 0;
this.pages = pages;
this.price = price;
this.available = true;
}
public void borrowed() {
this.available = false;
borrowTimes++;
}
public void returned() {
this.available = true;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_16.md",
"notebook_enable": false,
"exercise_id": "2d36930d6d0944ee86b854948c05d149"
}
\ No newline at end of file
# 题目16
在Student类中实现`public Book borrowBook(String name, BookType type);`方法,作用是获取名字为name且属性为type的的Book对象,修改学生的借书次数、书籍的被借阅次数和书籍的借阅状态。
建议:借助Book类的`borrowed()`方法和LibraryManager类的`getBook()`方法。
## 答案
```java
public abstract class Student {
private int id;
private String name;
private int borrowTimes;
private int age;
private LibraryManager manager;
public Student(String name, int age, LibraryManager manager) {
this.id = IDHolder.fetchStuId();
this.name = name;
this.age = age;
this.borrowTimes = 0;
this.manager = manager;
}
public Book borrowBook(String name, BookType type) {
Book book = null;
try {
book = manager.getBook(name, type);
} catch (NullPointerException e) {
e.printStackTrace();
System.out.println("I catch the null pointer!");
}
if (book == null) {
return null;
}
borrowTimes++;
book.borrowed();
return book;
}
}
```
## 选项
## 补充
题目12的意图是封装LibraryManager类的获取Book对象的方法,从而在Student类的`borrowBook()`方法中,只需要调用`manager.getBook()`而非`manager.getBookShelf().getBook()`
这样有效地较低了类之间(Student和BookShelf)的耦合度,符合设计原则中的“最少知识原则”。
{
"type": "code_options",
"author": null,
"source": "exercise_17.md",
"notebook_enable": false,
"exercise_id": "4906b0fc62a64506ab31421e1a02f43b"
}
\ No newline at end of file
# 题目17
在Student类中实现`public Book retrunBook(String name, BookType type);`方法,作用是返还名字为name且属性为type的的Book对象,通过修改书籍的借阅状态实现。
## 答案
```java
public abstract class Student {
private int id;
private String name;
private int borrowTimes;
private int age;
private LibraryManager manager;
public Student(String name, int age, LibraryManager manager) {
this.id = IDHolder.fetchStuId();
this.name = name;
this.age = age;
this.borrowTimes = 0;
this.manager = manager;
}
public Book borrowBook(String name, BookType type) {
Book book = null;
try {
book = manager.getBook(name, type);
} catch (NullPointerException e) {
e.printStackTrace();
System.out.println("I catch the null pointer!");
}
if (book == null) {
return null;
}
borrowTimes++;
book.borrowed();
return book;
}
public void returnBook(String name, BookType type) {
Book book = null;
try {
book = manager.getBook(name, type);
} catch (NullPointerException e) {
e.printStackTrace();
System.out.println("I catch the null pointer!");
}
if (book == null) {
return;
}
book.returned();
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_2.md",
"notebook_enable": false,
"exercise_id": "cab3d7435db24f17abc87106cee23b75"
}
\ No newline at end of file
# 题目2
在BookShelf类中定义一个构造方法`public BookShelf(BookType type);`,构造一个type属性为参数type的**空书架**,其中shelf属性使用ArrayList实现。
## 答案
```java
import java.util.List;
public class BookShelf {
private List<Book> shelf;
private BookType type;
public BookShelf(BookType type) {
this.shelf = new ArrayList<>();
this.type = type;
}
}
```
## 选项
## 补充
一些同学会好奇,为什么参数里面shelf的类型是List,而实现却是用ArrayList实现的。其实这是面向对象三大特性之一——多态,多态的一个特点就是父类引用子类实例,而在我们的ArrayList源代码中,是这么声明的:
```java
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
...
}
```
ArrayList实现了List接口,因此可以用List引用ArrayList实例。
{
"type": "code_options",
"author": null,
"source": "exercise_3.md",
"notebook_enable": false,
"exercise_id": "a3440336293c4f379858bcac10cbec36"
}
\ No newline at end of file
# 题目3
在BookShelf中,实现一个`public Book getBook(String name);`方法,从shelf中返回bookName属性值等于参数中name的Book对象,若没有,则返回null。
## 答案
```java
public class BookShelf {
private List<Book> shelf;
private BookType type;
public BookShelf(BookType type) {
this.shelf = new ArrayList<>();
this.type = type;
}
public Book getBook(String name) {
for (Book book: shelf) {
if (book.getBookName().equals(name)) {
return book;
}
}
return null;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_4.md",
"notebook_enable": false,
"exercise_id": "310522868d654406a931138967ec3657"
}
\ No newline at end of file
# 题目4
接着,我们新建Student**抽象类**,该类具有如下属性:
| 属性名 | 属性类别 | 说明 |
| ------------- | -------- | ------------ |
| id | int | 学生id |
| name | String | 学生姓名 |
| booksBorrowed | int | 学生借书次数 |
| age | int | 学生年龄 |
注意:这些属性都是private权限。
然后,我们修改IDHolder类,实现为Student类分配id的功能(注意和之前的方法区分开)。
最后,创建Student类的构造函数,该构造函数创建一个姓名为name,年龄为age的学生对象,
其中借书次数默认设置为0,id由IDHolder类自动分配。
## 答案
```java
public abstract class Student {
private int id;
private String name;
private int booksBorrowed;
private int age;
public Student(String name, int age) {
this.id = IDHolder.fetchStuId();
this.name = name;
this.age = age;
this.booksBorrowed = 0;
}
}
public class IDHolder {
private static int id = 1;
private static int stuId = 1;
public static int fetchId() {
return id++;
}
public static int fetchStuId() {
return stuId++;
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_5.md",
"notebook_enable": false,
"exercise_id": "e4329e2f04ee47e28f709c60c4add90d"
}
\ No newline at end of file
# 题目5
分别新建Freshman, Sophomore, Senior, Undergraduate四个类,都继承自Student类,并完成其构造方法。构造方法和父类Student的构造方法相同。
## 答案
```java
public class Freshman extends Student {
public Freshman(String name, int age) {
super(name, age);
}
}
public class Sophomore extends Student {
public Sophomore(String name, int age) {
super(name, age);
}
}
public class Senior extends Student {
public Senior(String name, int age) {
super(name, age);
}
}
public class Undergraduate extends Student {
public Undergraduate(String name, int age) {
super(name, age);
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_6.md",
"notebook_enable": false,
"exercise_id": "ac010eddd34d452ab416972c274db789"
}
\ No newline at end of file
# 题目6
新建LibraryManager类,用于对BookShelf类和Student类进行统一管理,该类具有如下属性:
| 属性名 | 属性类别 | 说明 |
| -------- | ------------------------ | --------------- |
| lib | Map<BookType, BookShelf> | 种类-书架对应表 |
| students | List\<Student\> | 学生列表 |
注意:这些属性都是private权限。
## 答案
```java
public class LibraryManager {
private Map<BookType, BookShelf> lib;
private List<Student> students;
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_7.md",
"notebook_enable": false,
"exercise_id": "397ada79a20e474b83e3076d8fb1d86e"
}
\ No newline at end of file
# 题目7
在LibraryManager类中,实现`public void addStudent(Student student);`方法,将student对象加入自身的学生列表中。
## 答案
```java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LibraryManager implements Subject {
private Map<BookType, BookShelf> lib;
private List<Student> students;
public LibraryManager() {
lib = new HashMap<>();
students = new ArrayList<>();
}
public void addStudent(Student student) {
students.add(student);
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_8.md",
"notebook_enable": false,
"exercise_id": "c5673900c35d491cb035ffc727e5131a"
}
\ No newline at end of file
# 题目8
在LibraryManager类中,实现`public void addBookShelf(BookType type);`方法,在lib中新增属性为type的书架。
## 答案
```java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LibraryManager implements Subject {
private Map<BookType, BookShelf> lib;
private List<Student> students;
public LibraryManager() {
lib = new HashMap<>();
students = new ArrayList<>();
}
public void addStudent(Student student) {
students.add(student);
}
public void addBookShelf(BookType type) throws TypeExistsException {
lib.put(type, new BookShelf(type));
}
}
```
## 选项
{
"type": "code_options",
"author": null,
"source": "exercise_9.md",
"notebook_enable": false,
"exercise_id": "82ad0de4e90d4bffbcfeb4ad81c1b51e"
}
\ No newline at end of file
# 题目9
在LibraryManager类中,实现`public BookShelf getBookShelf(BookType type);`,如果lib中有属性为type的书架,则返回该书架,否则返回null。
## 答案
```java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LibraryManager implements Subject {
private Map<BookType, BookShelf> lib;
private List<Student> students;
public LibraryManager() {
lib = new HashMap<>();
students = new ArrayList<>();
}
public void addStudent(Student student) {
students.add(student);
}
public void addBookShelf(BookType type) throws TypeExistsException {
lib.put(type, new BookShelf(type));
}
public BookShelf getBookShelf(BookType type) {
if (lib.containsKey(type)) {
return lib.get(type);
}
return null;
}
}
```
## 选项
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册