---
# System prepended metadata

title: Lab1 題目
tags: [CTBC-Lab1, CTBC]

---

# 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}`

![](https://i.imgur.com/G4O3YFp.png)


## 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實作
* 修改介面與實作,使用幾個測試的例子來說明你的實作
    * 如何新增一個類別
    * 如何在一個類別下新增另一個類別
    * 如何在一個類別下新增一個課程
    * 如何列出一個課程所在的類別

