Ôn tập: hệ phân cấp nhân viên
Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 40 trên 107.
Thử thách
DễHãy xây dựng hệ thống phân cấp nhân viên cho một công ty để minh họa cách kết hợp thành phần mô hình hóa cấu trúc tổ chức ngoài đời thực một cách tinh tế. Bạn sẽ tạo một kiểu nhân viên cơ sở để các vai trò chuyên biệt có thể mở rộng với những hành vi riêng.
Bạn sẽ sắp xếp code trong ba tệp:
employee.go: Tạo nền tảng với một cấu trúcEmployeegồm các trườngID,NamevàBaseSalary(float64). Tạo cho cấu trúc này hai phương thức:Info() stringtrả về[ID] [Name]CalculateBonus() float64trả về 10% lương cơ bản
roles.go: Tạo hai kiểu nhân viên chuyên biệt nhúngEmployee:Managercó trườngTeamSize(int): quản lý nhận tiền thưởng cao hơn, bằng 20% lương cơ bản cộng thêm $100 cho mỗi thành viên trong nhóm. Ghi đè phương thứcCalculateBonusđể triển khai cách tính này.Developercó trườngLanguage(string): lập trình viên nhận mức thưởng tiêu chuẩn nhưng ghi đè phương thứcInfođể thêm ngôn ngữ lập trình của họ:[ID] [Name] ([Language])
main.go: Đọc thông tin nhân viên từ đầu vào, tạo một Manager và một Developer, sau đó hiển thị thông tin và tiền thưởng đã tính của từng nhân viên.
Dữ liệu đầu vào sẽ gồm:
- Dòng 1: ID của Manager
- Dòng 2: Tên của Manager
- Dòng 3: Lương cơ bản của Manager (float64)
- Dòng 4: Quy mô nhóm của Manager (số nguyên)
- Dòng 5: ID của Developer
- Dòng 6: Tên của Developer
- Dòng 7: Lương cơ bản của Developer (float64)
- Dòng 8: Ngôn ngữ lập trình của Developer
Với mỗi nhân viên, hãy in thông tin của họ, rồi in tiền thưởng ở dòng tiếp theo. Định dạng tiền thưởng với hai chữ số thập phân.
Ví dụ, với M001, Sarah Chen, 80000, 5, D001, Alex Rivera, 65000 và Go, đầu ra sẽ là:
M001 Sarah Chen
16500.00
D001 Alex Rivera (Go)
6500.00Lưu ý cách tính tiền thưởng của Manager (20% của 80000 + 5×100 = 16500) khác với mức thưởng tiêu chuẩn 10% của Developer, trong khi Developer tùy chỉnh cách hiển thị thông tin của mình. Cả hai kiểu vẫn có quyền truy cập vào các trường Employee được nhúng và có thể gọi các phương thức ban đầu khi cần.
Tự làm thử
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// Đọc thông tin của Manager
managerID, _ := reader.ReadString('\n')
managerID = strings.TrimSpace(managerID)
managerName, _ := reader.ReadString('\n')
managerName = strings.TrimSpace(managerName)
managerSalaryStr, _ := reader.ReadString('\n')
managerSalary, _ := strconv.ParseFloat(strings.TrimSpace(managerSalaryStr), 64)
teamSizeStr, _ := reader.ReadString('\n')
teamSize, _ := strconv.Atoi(strings.TrimSpace(teamSizeStr))
// Đọc thông tin của Developer
devID, _ := reader.ReadString('\n')
devID = strings.TrimSpace(devID)
devName, _ := reader.ReadString('\n')
devName = strings.TrimSpace(devName)
devSalaryStr, _ := reader.ReadString('\n')
devSalary, _ := strconv.ParseFloat(strings.TrimSpace(devSalaryStr), 64)
devLanguage, _ := reader.ReadString('\n')
devLanguage = strings.TrimSpace(devLanguage)
// TODO: Tạo Manager bằng các giá trị đã đọc
// Gợi ý: Dùng cấu trúc kết hợp, Manager nhúng Employee
// TODO: Tạo Developer bằng các giá trị đã đọc
// Gợi ý: Dùng cấu trúc kết hợp, Developer nhúng Employee
// TODO: In thông tin và tiền thưởng của Manager (định dạng tiền thưởng với 2 chữ số thập phân)
// Dùng fmt.Printf với "%.2f" để định dạng
// TODO: In thông tin và tiền thưởng của Developer (định dạng tiền thưởng với 2 chữ số thập phân)
}
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng OOP trong Go
Tệp bên ngoàiWorkspace và module trong GoPackage và importTên được export và không được exportGiới thiệu về OOP trong GoStruct như lớpĐịnh nghĩa phương thức cho structReceiver kiểu con trỏ và kiểu giá trịKhởi tạo structHàm khởi tạoÔn tập: máy tính đơn giản4Interface
Giới thiệu về interfaceTriển khai ngầm địnhInterface như một hợp đồngInterface rỗng (any)Khẳng định kiểuswitch kiểuKết hợp interfaceInterface Stringer và ErrorÔn tập: Máy tính hình học7Tính đóng gói
Trường được xuất và không được xuấtĐóng gói ở cấp packagePhương thức getter và setterẨn thông tin trong GoÔn tập: hồ sơ học sinh10Generics (Go 1.18 trở lên)
Giới thiệu về GenericsTham số kiểuRàng buộc kiểuStruct tổng quátGiải pháp thay thế cho phương thức tổng quátÔn tập: tập hợp tổng quát13Các mẫu thiết kế phần 1
Giới thiệu về mẫu thiết kếMẫu SingletonMẫu FactoryMẫu Abstract FactoryMẫu ObserverMẫu Strategy2Tìm hiểu chuyên sâu về kiểu dữ liệu và struct
Kiểu cơ bản và kiểu tổng hợpĐịnh nghĩa kiểu dữ liệu tùy chỉnhThẻ structStruct ẩn danhStruct lồng nhauGiá trị zero và giá trị mặc địnhÔn tập: sổ liên lạc5Ưu tiên kết hợp hơn kế thừa
Vì sao Go không có kế thừaNhập môn nhúng structTự động nâng phương thứcNhúng nhiều structNhúng và kết tậpChe khuất phương thức được nhúngÔn tập: hệ phân cấp nhân viên8Xử lý lỗi và lập trình hướng đối tượng
Giao diện errorCác kiểu lỗi tùy chỉnhBọc lỗi với fmt.ErrorfLỗi sentinelerrors.Is() và errors.As()Panic, defer và recoverÔn tập: trình phân tích tệp3Con trỏ và bộ nhớ
Cơ bản về con trỏ trong GoCon trỏ đến structTruyền theo giá trị và tham chiếuHàm new()Thu gom rác trong GoÔn tập: xây dựng danh sách liên kết6Đa hình trong Go
Đa hình qua interfaceĐịnh kiểu vịt trong GoQuy tắc thỏa mãn interfaceCác tập hợp đa hìnhTiêm phụ thuộcÔn tập: bộ xử lý thanh toán9Lập trình đồng thời và lập trình hướng đối tượng
Cơ bản về goroutineChannel và giao tiếpChannel có bộ đệm và không có bộ đệmCâu lệnh selectsync.Mutex và sync.RWMutexsync.WaitGroupThiết kế struct an toàn luồngÔn tập: worker poolTự luyện tập: Trình biên dịch Go online