חיפוש באמצעות ממשקים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 101 מתוך 107.
אתגר
קלבואו נוסיף יכולות חיפוש גמישות למערכת ניהול הספרייה שלנו! תממשו את תבנית האסטרטגיה באמצעות ממשקים, כך שהמשתמשים יוכלו לחפש ספרים לפי קריטריונים שונים בלי לשנות את קוד הליבה של הספרייה.
תארגנו את הקוד שלכם בחמישה קבצים:
book.go: המבנהBookשלכם משיעורים קודמים, עם השדותID,Title,Author,ISBNו-Available. כללו את הבנאיNewBook.user.go: המבנהUserשלכם, עם השדותID,Name,Emailו-BorrowedBooks. כללו את הבנאיNewUser.search.go: הגדירו את ממשק אסטרטגיית החיפוש ואת המימושים שלו.צרו ממשק
SearchStrategyעם מתודה אחת:Match(book *Book, query string) boolממשו שלוש אסטרטגיות חיפוש:
TitleSearch: מחזירה התאמה אם כותרת הספר מכילה את מחרוזת החיפוש (ללא תלות באותיות גדולות או קטנות)AuthorSearch: מחזירה התאמה אם שם מחבר הספר מכיל את מחרוזת החיפוש (ללא תלות באותיות גדולות או קטנות)ISBNSearch: מחזירה התאמה אם ה-ISBN של הספר זהה בדיוק למחרוזת החיפוש
library.go: המבנהLibraryשלכם, עם מפות לספרים ולמשתמשים. הוסיפו מתודהSearchשמקבלת כלSearchStrategyומחרוזת חיפוש, ומחזירה פרוסה של מצביעים לספרים תואמים. המתודה צריכה לעבור על כל הספרים ולהשתמש במתודהMatchשל האסטרטגיה כדי למצוא תוצאות.main.go: צרו ספרייה עם ספרים, ואז בצעו חיפושים באמצעות אסטרטגיות שונות.קראו את מספר הספרים, ואז עבור כל ספר קראו את המזהה, הכותרת, המחבר וה-ISBN שלו. לאחר מכן, קראו את מספר פעולות החיפוש. כל פעולה מורכבת מסוג חיפוש (
title,authorאוisbn) ואחריו מחרוזת החיפוש.עבור כל חיפוש, הדפיסו
Search by [type]: [query], ואחריו את מזהי הספרים התואמים בשורה הבאה, ממוינים בסדר עולה ומופרדים בפסיקים (מעבר על מפה מתבצע בסדר אקראי, לכן מיין את המזהים לפני ההדפסה). אם אין ספרים תואמים, הדפיסוNo resultsבמקום זאת.
הקלטים הבאים יסופקו:
- מספר הספרים, ואחריו המזהה, הכותרת, המחבר וה-ISBN של כל ספר (כל אחד בשורה נפרדת)
- מספר החיפושים, ואחריו סוג החיפוש ומחרוזת החיפוש של כל חיפוש (כל אחד בשורה נפרדת)
לדוגמה, בהינתן:
3
B001
The Go Programming Language
Alan Donovan
978-0134190440
B002
Go in Action
William Kennedy
978-1617291784
B003
Learning Python
Mark Lutz
978-1449355739
3
title
go
author
kennedy
isbn
978-1449355739הפלט שלכם צריך להיות:
Search by title: go
B001,B002
Search by author: kennedy
B002
Search by isbn: 978-1449355739
B003ובהינתן:
2
B001
Clean Code
Robert Martin
978-0132350884
B002
The Pragmatic Programmer
David Thomas
978-0135957059
2
title
java
author
martinהפלט שלכם צריך להיות:
Search by title: java
No results
Search by author: martin
B001ובהינתן:
2
B001
Design Patterns
Gang of Four
978-0201633610
B002
Head First Design Patterns
Eric Freeman
978-0596007126
1
title
designהפלט שלכם צריך להיות:
Search by title: design
B001,B002שימו לב איך המתודה Search עובדת עם כל אסטרטגיה. היא לא יודעת אם החיפוש מתבצע לפי כותרת, מחבר או ISBN. הגישה הפולימורפית הזו מאפשרת לכם להוסיף סוגי חיפוש חדשים (כמו חיפוש לפי זמינות או שנת פרסום) פשוט על ידי יצירת מבנים חדשים שמממשים את SearchStrategy!
נסו בעצמכם
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// קרא את מספר הספרים
numBooksStr, _ := reader.ReadString('\n')
numBooks, _ := strconv.Atoi(strings.TrimSpace(numBooksStr))
// צור ספרייה
library := NewLibrary()
// קרא את פרטי כל ספר
for i := 0; i < numBooks; i++ {
id, _ := reader.ReadString('\n')
id = strings.TrimSpace(id)
title, _ := reader.ReadString('\n')
title = strings.TrimSpace(title)
author, _ := reader.ReadString('\n')
author = strings.TrimSpace(author)
isbn, _ := reader.ReadString('\n')
isbn = strings.TrimSpace(isbn)
book := NewBook(id, title, author, isbn)
library.AddBook(book)
}
// קרא את מספר החיפושים
numSearchesStr, _ := reader.ReadString('\n')
numSearches, _ := strconv.Atoi(strings.TrimSpace(numSearchesStr))
// עבד כל חיפוש
for i := 0; i < numSearches; i++ {
searchType, _ := reader.ReadString('\n')
searchType = strings.TrimSpace(searchType)
query, _ := reader.ReadString('\n')
query = strings.TrimSpace(query)
// TODO: בחר את אסטרטגיית החיפוש המתאימה לפי searchType
// searchType יכול להיות "title", "author" או "isbn"
var strategy SearchStrategy
// TODO: ממש כאן את הלוגיקה לבחירת האסטרטגיה
// TODO: בצע את החיפוש באמצעות library.Search(strategy, query)
// TODO: הדפס את התוצאות בפורמט הנדרש
// פורמט: "Search by [type]: [query]" ואחריו מזהי הספרים התואמים או "No results"
fmt.Printf("Search by %s: %s\n", searchType, query)
// TODO: הדפס את מזהי הספרים התואמים מופרדים בפסיקים, או "No results"
_ = strategy // הסר את השורה הזו כשתממש את הפתרון
}
}
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP ב-Go
קבצים חיצונייםסביבת העבודה והמודולים של Goחבילות וייבואשמות מיוצאים לעומת שמות לא מיוצאיםמבוא ל-OOP ב-GoStructs כמחלקותהגדרת מתודות עבור Structsמקבלי Pointer לעומת Valueאתחול Structפונקציות Constructorחזרה – מחשבון פשוט4ממשקים
מבוא לממשקיםמימוש משתמעממשק כחוזהממשק ריק (any)אימות טיפוסמתג טיפוסיםהרכבת ממשקיםממשקי Stringer ו-Errorסיכום – מחשבון צורות7כימוס
שדות מיוצאים לעומת שדות לא מיוצאיםכימוס ברמת החבילהמתודות Getter ו-Setterהסתרת מידע ב-Goסיכום – רשומות תלמידים10Generics (Go 1.18 ומעלה)
מבוא ל־Genericsפרמטרים של טיפוסיםאילוצי טיפוסיםמבנים גנרייםפתרון עוקף למתודות גנריותסיכום – אוסף גנרי2העמקה בסוגים וב-Structs
סוגים בסיסיים ומורכביםהגדרות של סוגים מותאמים אישיתתגיות StructStructs אנונימייםStructs מקונניםערכי אפס וברירות מחדלסיכום – ספר אנשי קשר5קומפוזיציה במקום ירושה
למה ב-Go אין ירושהיסודות הטמעת Structקידום מתודותהטמעת כמה Structsהטמעה לעומת אגרגציההסתרת מתודות מוטמעותסיכום – היררכיית עובדים8טיפול בשגיאות ו-OOP
ממשק errorסוגי שגיאות מותאמים אישיתעטיפת שגיאות (fmt.Errorf)שגיאות Sentinelerrors.Is() ו-errors.As()Panic, Defer ו-Recoverסיכום – מנתח קבצים11ספרייה סטנדרטית ותכנות מונחה עצמים
io.Reader ו-io.Writersort.Interfaceהממשק fmt.Stringerencoding/json עם מבניםהממשק http.Handlerסיכום – מודלים של REST API3מצביעים וזיכרון
יסודות המצביעים ב-Goמצביעים למבניםהעברה לפי ערך לעומת לפי הפניההפונקציה new()איסוף אשפה ב-Goסיכום - בונה רשימה מקושרת6פולימורפיזם ב-Go
פולימורפיזם באמצעות ממשקיםטיפוס ברווז ב-Goכללי התאמה לממשקאוספים פולימורפייםהזרקת תלויותסיכום - מעבד תשלומים9מקביליות ו-OOP
יסודות GoroutinesChannels ותקשורתChannel עם חוצץ לעומת ללא חוצץפקודת Selectsync.Mutex ו-sync.RWMutexsync.WaitGroupתכנון Struct בטוח לשימוש במקבילסיכום - מאגר עובדים12מושגים מתקדמים בתכנות מונחה עצמים
דפוס האפשרויות הפונקציונליותדפוס Builder ב-Goשרשור מתודותכינויי טיפוסים לעומת הגדרותיסודות Reflectionסקירה כללית של יצירת קוד15פרויקט: ניהול ספרייה
סקירה כללית ומבנה הפרויקטמבני נתונים של ספרים ומשתמשיםתרגלו בעצמכם: קומפיילר Go אונליין