# Lab1 題目
###### tags: `CTBC-Lab1` `CTBC`
## 1. 實作DomainObject
建立model子套件
### 1.1 實作課程分類的類別
* 可以使用lombok的標記或者自行實作存取函數
* hint: @Getter,@Setter
* 每個屬性都是私有的
* 每個類別需要有沒有參數的預設建構子??
* https://ithelp.ithome.com.tw/m/articles/10267747
* 在此處不要使用@Data
* 在model下建立類別CourseCategory
* 1.1.1 類別的識別碼(ID)是UUID
* https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/UUID.html
* 1.1.2 類別有名稱
* 1.1.3 類別有細節
* 1.1.4 其餘想到的欄位
### 1.2 實作描述課程本體的類別
* 1.2.1 課程的識別碼(ID)是UUID
* 1.2.2 課程有名稱
* 1.2.3 課程有價錢(Integer)
* 1.2.4 課程有類別
### 1.3 建立測試
* 1.3.1 建立lab1子套件,在其中實作第一部份的測試
* 1.3.2 測試建構子可順利生成
* 預設建構子
* 所有參數建構子 ??
* 1.3.3 測試任意存取函數 ??
## 2. 實作領域物件的存取Service介面
建立service子套件於程式目錄下
### 2.1 設計interface
#### 2.1.1 設計類別服務界面
* 2.1.1.1 列出所有的類別
* 2.1.1.2 依照屬性新增類別,並且傳回類別 (屬性??)
* 參數中不需要包含UUID
* 2.1.1.3 依照鍵值刪除類別
* 2.1.1.4 依照鍵值與新的值修改,並且傳回修改後的類別
#### 2.1.2 設計課程服務界面
* 2.1.2.1 列出所有的課程
* 2.1.2.2 依照屬性新增課程,並且傳回課程 (屬性??)
* 參數中不需要包含UUID
* 2.1.2.3 依照鍵值刪除課程
* 2.1.2.4 依照鍵值與新的值修改,並且傳回修改後的課程
### 2.2 實作interface
在 servive子套件目錄下
#### 2.2.1 實作CourseCategoryServiceJDKImplement
* 2.2.1.1 實作出類別管理的物件實作類別界面
* 類別管理??
* 2.2.1.2 使用JDK中原生的資料結構表示即可
* 2.2.1.3 在新增時指定一組UUID
* 2.2.1.4 刪除時如果UUID不存在傳回null (△)
* 2.2.1.5 修改時如果UUID不存在傳回null不修改,如果存在則照必要的修改 (△)
#### 2.2.2 實作CourseServiceJDKImplement
* 2.2.2.1 實作出課程管理的物件實作課程界面
* 2.2.2.2 使用JDK中原生的資料結構表示即可
* 2.2.2.3 在新增時指定一組UUID (△)
* 2.2.2.4 修改時如果UUID不存在傳回null不修改,如果存在則照必要的修改 (△)
* `if (courseMap.getCourseId == null){return null}`

## 3. 使用單元測試測試實作的介面
### 建立lab3子套件
對於課程與課程類別的服務
* 3.1 服務生成時可以取出所有的但是是為空
* 3.2 測試加入一筆後比較內容
* 使用`assertEquals()`
* 3.3 測試加入多筆之後比較內容
* 使用`assertEquals()`
* 3.4 測試正確刪除之後比較內容
* 3.5 測試UUID不存在時刪除沒有影響 (△)
* 3.6 測試UUID錯誤時修改傳回為空 (△)
* 3.7 其它想到的測試
## 4. 實作類別到課程的對應,該如何表達類別中有的課程? (△)
在類別中增加一個List來儲存課程,並且完成以下的邏輯
* 4.1 將課程加到類別
* 4.2 如果課程加到另一個類別,把課程從原本類別中移除
* 4.4 對原本的程式與測試程式作必要的修改
* 4.4 撰寫單元測試驗證是否正確
* 例如將沒有類別的課程加入某類別並且驗證
* 例如將有類別的課程移至另一個類別並且作驗證
## 5. 實作例外
建立exception子套件
* 5.1 課程名稱重複的例外
* `equals()`
* 5.2 類別ID不存在的例外
*
* 5.3 撰寫測試程式,測試例外的發生
* https://junit.org/junit5/docs/current/user-guide/#extensions-exception-handling
## 6. 實作Factory (△)
* 6.1 使用測試程式說明目前的Service每次生成都是不一樣的實例
* 6.2 實作Factory讓Service能生成同一個實例
* 6.2.1 建立util子套件
* 6.2.2 建立CourseServiceFactory
* 6.3 使用單元測試測試
* 參考之程式碼
:::spoiler Factory
```java
// Factory P.225~226
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
interface Shape{
public void onDraw();
}
class Circle implements Shape{
private float pointX, pointY;
private float radius;
public Circle(float pointX, float pointY, float radius) {
super();
this.pointX = pointX;
this.pointY = pointY;
this.radius = radius;
}
@Override
public void onDraw() {
System.out.printf("draw a circle with(%2f,%2f), radius = %.2f\n", pointX, pointY, radius);
}
}
class Rectengle implements Shape{
private float pointX, pointY;
private float width, height;
public Rectengle(float pointX, float pointY, float width, float height) {
super();
this.pointX = pointX;
this.pointY = pointY;
this.width = width;
this.height = height;
}
@Override
public void onDraw() {
System.out.printf("draw a rectangle with(%2f,%2f), radius = %.2f\n", pointX, pointY, width, height);
}
}
class Canvas {
private List<Shape> shapes = new ArrayList<Shape>();
public void addShape(String type) {
Shape shape = ShapeFactory.getShape(type);
shapes.add(shape);
}
public void onDraw() {
Iterator<Shape> iterator = shapes.iterator();
while(iterator.hasNext()){
Shape currentShape = iterator.next();
currentShape.onDraw();
}
}
}
class ShapeFactory{
public static Shape getShape(String type) {
switch (type) {
case "Circle":
return new Circle(50.0f,50.0f,30.0f);
case "Rectangle":
return new Rectengle(30,30,5,5);
}
return null;
}
}
public class MainTest {
public static void main(String[] args) {
Canvas canvas = new Canvas();
canvas.addShape("Circle");
canvas.addShape("Circle");
canvas.addShape("Rectangle");
canvas.onDraw();
}
}
```
:::
## 7. 多執行緒時的考量 (△)
* 7.1 多執行緒時的考量
* 7.1.1 如何模擬生成Service時需要較長時間,此時仍無法保持singleton
* 7.1.2 修改factory,並且實作出測試
* 7.2 如何在多執行緒時依然保持threadsafe?
## 自由發揮
* 如何實作多階層類別?
* 設定根目錄,用LinkedList或是Recursion實作
* 修改介面與實作,使用幾個測試的例子來說明你的實作
* 如何新增一個類別
* 如何在一個類別下新增另一個類別
* 如何在一個類別下新增一個課程
* 如何列出一個課程所在的類別