---
# System prepended metadata

title: 物件導向 - 鄭永斌
tags: [學校, 大三下]

---

# 物件導向 - 鄭永斌


## 2.

- 會按照繼承的順序依序執行父類的建構子，倒著執行解構子。每一個 subclass 要自行負責建構與清除自己特異化的部分
- member initialization list：`Rat(int w) : Pet(w){}`，執行指定的父類建構子
- overload 多載 != polymorphism 多型
- 如果 override 一個在父類 overloaded (名字一樣，參數不一樣)的 method，沒被 override 的其他同名 method 都會不見，無法被call。(因為編譯器要你確定全都有 override)
- `(Pet) Cat.speak()`：轉型時，compiler會自動 call copy constructor，之後再 destruct 掉

## 3. Polymorphism

用 base class 的指標來處理時，可以根據 subclass 做不同的處理
e.g.
```c
for(Entity E in list) {
  E->draw();
}
```
以下是說 c++

- 任何想被子類 override 的 method 都要宣告成 virtual，一旦被宣告成 virtual，在子類中都會是 virtual，但還是建議加一下比較好'
- 多型只對 pointer、reference，以及宣告成 virtual 的函式有效
- 如果一個 class 有任何一個 method 是 virtual 的，destructor 也要是 virtual
- 總之就是子類可能會自己特異化實現的用 virtual，但不要乾脆就全 virtual，因為有 overhead
- **object slicing**：pass by value 的時候，如果參數型別是基類，那傳子類進去時，子類的記憶體會被切掉，只會copy出一個基類物件
- 以前 C 沒有 OO 的時候就要 hardcode switch 來做多型，或是用 function pointer 和 function array
- **Indirect call**：間接呼叫，利用存在暫存器中的地址在執行時定址。e.g. `MOV [EBX], 123`
- **binding**：把記憶體位址綁到 call function 的地方
  - ++compilation time binding++：自己寫的函式
  - ++linking time binding++：C 內建的函式
  - ++loading time binding++：去外界參考表找 function 的位址，而位址要等OS把DLL(dynamic linking library)載入到記憶體後再填進去
    ![image](https://hackmd.io/_uploads/S1jh5Vk21l.png)
- Dynamic Binding：維護並使用 Virtual Function Table，一個 class 只會有一個，各實例共用
  ![image](https://hackmd.io/_uploads/SJiKfS1nJl.png)
- abstract class：有純虛函式 pure virtual function `virtual void myFunc() = 0;`，因此不可能有這 class 的實例

## 4. Multiple Inheritance

- **Percolating Upward**：為了多型，把子類特異化的部分移到父類
- `dynamic_cast<[TYPE]> [VAR]`：試著把 `VAR` 轉成 `[TYPE]` 並回傳，不行就回傳 `NULL`
- casting up / down：轉成 父/子 類
- Percolating Upward 跟 Casting Down 都是 bad design，因為無法做到 ++跟未來擴充型別無關++，無法應付未來的擴充，需要回去改 code
- 多重繼承：子類繼承自兩個父類，兩個父類又繼承自同一個祖父類，則子類會 call 兩次祖父類的 constructor，並且會有兩個祖父類的記憶體空間
  ![image](https://hackmd.io/_uploads/B1GolCfhkl.png)

### c++

- 因為這樣重複的記憶體會有 ambiguity，所以 C++ 有提供一些解法
  - 指定：`jetCar->Jet::stop()`，甚至是 `jetCar->Jet::Vehicle::run()`
  - 子類 override 掉
- 但就算這樣有時還是不對，比如說祖父類的 "資料" 會有兩份
- **Diamond-shaped Inheritance**：鑽石型繼承，父類在繼承祖父類時使用 `virtual` 關鍵字，在多重繼承時就只會有一個祖父類

### java

- **Interface**：就是一個只能宣告純虛函式的 class，要繼承的話要用關鍵字 `implement`，然後子類自己填定義
- 介面的使用原則：A implement B，表示 A **can do** B

## 5. Comparison of Java and C++

- Java 如果要呼叫父類的建構子要用 `super()` 而且這只能在子類建構子的第一行 call，也不能用任何的 `this.xxx` 來當參數
- `super.func()`：可用來 call 父類被覆寫的函式
- `myClass[100]`：C++ 會建立 100 個物件呼叫 100 次建構子；Java 不會，只會建立 reference，所以不會 call 建構子，要之後自己 new 物件
- Java 的 primitive type 都是 pass by value；class type 都是 pass by reference
- Java 沒有 global variable

## 6. Code Quality

沒什麼特別的

## 7. DataBase Design and Normalization

- Normalization：只讓資料庫包含恰恰能描述的資料
  - 移除重複的冗餘資料 (去除重複的column)
  - 確保關連性合理
- foriegn key：連到另一個 table 的 column
- **1st Normal Form**
  ![image](https://hackmd.io/_uploads/rJj2Zobakg.png =40%x) ![image](https://hackmd.io/_uploads/r1VJfjZ6Je.png =40%x)
- **2nd Normal Form**
  移除跟 primary key 無關聯的 column
  ![image](https://hackmd.io/_uploads/H1cwQiW61x.png =60%x)
- **3rd Normal Form**
  Non-key value 不能有相關性
  ![image](https://hackmd.io/_uploads/S1DAUoZ6Jg.png)

## 8. Data-Oriented Model

- middle-level notation：把設計系統時的心路歷程記下來，希望可以把高手的作法歸結出一個能照著做的方法論
- **ERD**：Entity-Relation Diagram，專注在data間如何link跟組織
- The Entity Relationship **Principle**：list of ***things***
- Entity type = class = 一個 table
- Entity = object
- Occurrence = instance
- Attribute = 一個欄位
- Assotioation： 動作 = 一個 Access path way (i.e. foreign key)
- 各種 programming language 的發明都是為了解決 software engineering 的問題
- 物件導向的程式就是為了避免之後要一直改
- Multiplicity：多對一、一對多、many-to-many

## 9. How to find classes and objects

- **Jacobson's Three Types**
  - **Entity objects**：things in the users' real world
    - ++concrete objects++：Employee, Product, Tool, etc
    - ++Conceptual objects++：Corporation, strategy, membership, approval, etc
    - ++Event and State objects++：Purchase, delivery, arrival, ownership, status, etc
  - **Interface objects**：comminucation protocol，GUI、真實世界的SOP、既有系統的interface, etc
  - **Control objects**：To carry complex methods that don't have a class they obviously belong in
- **The KRB Seven-Step Method**
  1. ++Candidate Classes++：列出跟你的project有關的所有名詞(name)，也許能當class
  2. ++Define Classes++：決定要有哪些class，每個候選的class都需要經過下列三個檢查
     1. A Real-World Identifier："How do I tell one ... from another?" 這class的物件彼此間能不能區分(每位學生都不同)
     2. A Definition："What is a ... ?"，能不能用一句話給這物件一個定義
     3. Sample Attributes and Behaviors
  3. ++Establish Associations++：物件的互動
     ![image](https://hackmd.io/_uploads/Hk6oDcLyxg.png =60%x)
  4. ++Expand Many-to-Many Associations++：新增class去解掉M:M的情況
     ![image](https://hackmd.io/_uploads/ByV0dqLylx.png =48%x) ![image](https://hackmd.io/_uploads/S1E7tq8Jle.png =45%x)
  5. ++Attributes++：列出每個物件需要有的屬性
  6. ++Normalization++：正規化，database的事情
  7. ++Operations++：Behavior，物件的method
  8. 根據物件的相似性建構繼承關係

## 10. Overview of UML

物件導向除了可重用、好維護外，還有一個重要的點是可以 modeling software before building it

- UML：Unified Modeling Language

## 12. UML class diagram

- composit：sub class 擁有 base class 型別的物件

### Class Diagram

- 描述系統中物件的 class，以及 class 間的**靜態**關聯
- Assotiation：class 間的連線箭頭表示，擁有者指向被擁有者，但 UML 2.x 移除的，不用箭頭
- Generalization 空心箭頭，表示繼承自

![image](https://hackmd.io/_uploads/Sk8pHn_xxx.png =70%x)

### Object Diagram

又被稱作 instance diagram，是系統的快照

![image](https://hackmd.io/_uploads/HJSyLhulxg.png =70%x)

method 畫底線是 class scope (static) 的
![image](https://hackmd.io/_uploads/SkPzIndelx.png =70%x)

### Multiple Classification

連接線上的 Discriminator 解釋特異化的意義
(實心箭頭表示不能再被繼承下去)

![image](https://hackmd.io/_uploads/S1suLnuxgx.png =70%x)

### Dynamic Classification

標一個 \<<dynamic\>> 表示型別可能會互相轉換

![image](https://hackmd.io/_uploads/S1qaw2Olee.png =70%x)

### Aggregation and Composition

association 的一種

- Aggregation：聚集，一個沒了另一個還能存在。空白菱形
- Composition：合成，不可分割，同生同滅。實心菱形

菱形都是指向大的那邊

![image](https://hackmd.io/_uploads/Byfyc2_xge.png =70%x)

### Derived Association and Attribute

衍生的關聯或屬性，用 `/` 標註，實作時不須用一個欄位紀錄，從其他關連或屬性去推就好，比如說有++生日++就不用記++歲數++

![image](https://hackmd.io/_uploads/rygdj2ulgg.png =70%x)

### Interface and Abstract Class

用虛線
- Abstract
  ![image](https://hackmd.io/_uploads/SJHn23_gxe.png =70%x)
- Interface
  ![image](https://hackmd.io/_uploads/rylwA3Oele.png =70%x )
  
### Classification and Generalization

1. 小白是狗
2. 狗是物種

但小白不是物種

雖然他們口語都是 is-a 關係，但 Generalization (繼承)有遞移性 classification 沒有遞移性

### Qualified Association

三小

![image](https://hackmd.io/_uploads/Hy1BW6uxlg.png =70%x)

### Association Class

給連線一個 class
![image](https://hackmd.io/_uploads/SyZSM6ulxg.png =70%x)
其實就是省略一些中間 class，上圖等價下圖
![image](https://hackmd.io/_uploads/H1y7zadxle.png =70%x)

### Template Class

C++ 的 template，標在右上角
![image](https://hackmd.io/_uploads/B1tW7Tuglg.png =70%x)
![image](https://hackmd.io/_uploads/SJmEQauxle.png =70%x)

### 箭頭

knows a 是只有指標，has a 是創建跟刪除物件

![image](https://hackmd.io/_uploads/H1ITMQFlxe.png)

## 13 UML sequence diagram

- 又叫 interaction diagram，描述 objects (不是class) 間如何合作完成一件事
  - sequence diagram
  - collaboration diagram

### sequence diagram

- 由上到下表時間順序
- `*` 表示有 for loop
  ![image](https://hackmd.io/_uploads/r1zxB3Klxe.png =70%x)
- 半個箭頭表示 asynchronous
  ![image](https://hackmd.io/_uploads/r1GVI3Yell.png)
- sequence diagram 不擅長展示有loop等的演算法，適合用來展示複雜的互動環境
  ![image](https://hackmd.io/_uploads/Hy0CwnKglg.png =70%x)
  (中間小圈O->是傳參數)
  ![image](https://hackmd.io/_uploads/r1pm_2Fxle.png =70%x)

### collaboration diagram

- 因為 sequence diagram 很容易太長，所以 collaboration diagram 改用數字標執行順序，不寫成一條了。
![image](https://hackmd.io/_uploads/SkNEthtxll.png =70%x)

### How to find methods of object

- two method
  - **Maximize**：如果是要寫 library，設計物件的時候不知道別人會怎麼用，那就多寫一點method
  - **Minimize**：如果是自己要完成一個軟體。那就不要寫不會用到的 method

## 11. Movie rental Example

- 一個設計是否良善要看未來維護需求是甚麼
- software entropy：愈來愈亂

### State Pattern

將一個物件的多種狀態封裝在不同的類別中，從而使狀態轉換更為靈活和可維護
跟 Strategy Pattern 看起來很像，但一個是狀態轉移，一個是行為更換。State Pattern 的行為邏輯沒有被抽出來，Strategy的有。

## 14. Design Pattern 1

有本四人幫(The gang of Four)的書能看

- **Design Pattern**：過去在實作各種各類的軟體過程中，許多人累積了寶貴的物件導向分析經驗。經過蒐集整理，這些寶貴的繼承架構，class diagram，物件互動架構等等，被蒐集成所謂的design patterns
- **KISS**：Keep It Simple and Stupid

### Composite Pattern
- 如果物件用composite 包含 base class，那就不要把特異化放在 sub class 了，直接 percolating up 放到 base class，不然還要判斷當前物件是甚麼類型才能 call 特異化的部分
  ![image](https://hackmd.io/_uploads/rkB1XBsWxx.png)

### Proxy Pattern

### Singleton Pattern

- Global Variable is EVIL：不知道誰能存取它、耦合、汙染命名空間、多執行緒會有 concurrency 的問題
- Singleton：建構子是 private，物件等需要(第一次get)才建立，確保 class 只有一個 instance

### Strategy Pattern

- composition 可能比繼承好
- 假設有各種鴨子，++綠頭鴨++、++橡皮鴨++、++木雕鴨++，如果都繼承自「鴨子」，而鴨子有++叫++、++飛++等 function，那++橡皮鴨++、++木雕鴨++都需要各自override它們為空，導致代碼重用性很差。唉，總之就是物件裡面的方法再拉出來寫成另一個物件（比如說這些行為物件可能是實現一個叫做 behavior 的 interface 之類的）這樣就可以在物件間 reuse，甚至還能在 runtime 抽換掉 (如果用繼承來搞不同物件的行為的話，就沒法在 runtime 轉成另一個 sub class 了)
  ![image](https://hackmd.io/_uploads/HkQv-IsZgl.png)

## 15. Design Pattern 2

### Factory Pattern

> [!Note] Design Principle
> **Close for Modifications**：要改code的時候不用到處改，那就要把核心 code 都用 interface 跟多型（Program to an interface, not an implementation）
> 
> **Dependency Inversion Principle**：高層類別不該依賴於底層類別，要搞抽象就全都抽象

把 `new Subtype1()` 這類創建物件的東東移到 factory 物件裡，要創建物件的時候，傳參數（string 或 enum 之類的）進去 Factory 的 `createObject(Type)`，總之就是把 `new Subtype1()` 抽出來，這樣以後要改或擴充的話，去 factory 改就好

並且如果 subtype 有再分化下去成 subsubtype 的話，factory也搞個繼承變 subFactory，`createObject(Type)` 也弄成 abstract 搞多型，天知道為啥這樣比較好
![image](https://hackmd.io/_uploads/S1GpUDibex.png =70%x)

![image](https://hackmd.io/_uploads/BkNnBPsZgl.png =70%x)

![image](https://hackmd.io/_uploads/HJyje_j-eg.png =30%x) $\Rightarrow$ ![image](https://hackmd.io/_uploads/ryY2x_iWgl.png =30%x)

或是再把 Factory 也從使用它的 class 中抽出來，改在建構時傳進去，更解耦合
![image](https://hackmd.io/_uploads/BJMvRvjbgg.png =50%x)

### Decorator Pattern

> [!Note] Design Principle
> Classes should be open for extension, but closed for modification

用有點像 composition 那樣的方式，從基底 class 一層一層包 decorator 上去，達到類似繼承的差異化

![image](https://hackmd.io/_uploads/B1W8aFj-eg.png =80%x)

舉例來說，有不同的咖啡，以及不同的配料，要計算價錢，那就基底看要哪種咖啡，然後一層一層加不同配料上去，每個 decorator 和基底 class 都有 `getCost()` function，要用的時候從最外面一層層 call 進去
![image](https://hackmd.io/_uploads/BkHZwFi-gx.png =60%x)
![image](https://hackmd.io/_uploads/H17naYo-ge.png =80%x)
![image](https://hackmd.io/_uploads/B15CTts-gl.png =70%x)


### Model View Control 

> GUI 是軟體中最常面對變動的東東

- Model：the computational model
- View：負責把 data 畫出來
- Controller：負責 user event，然後跟 model 互動（本身不該有運算邏輯的部分，只負責怎麼把資料給 View）

![image](https://hackmd.io/_uploads/ByOfam2Zgg.png =80%x)

#### Observer Pattern

Observer Pattern 定義了一種一對多的依賴關係，讓一個或多個觀察者物件監聽其所關心的主題物件。當這個主題物件發生狀態改變時，會對所有的觀察者發送通知。
 ![image](https://hackmd.io/_uploads/B1fvgN2beg.png =70%x)
