You are on page 1of 22

‫‪1‬‬

‫תיכון מונחה עצמים ‪ -‬בחינה מועד א‬


‫מס’ קורס ‪10054 :‬‬
‫סמס’ ב תשפ"ב‬
‫מרצה ‪ :‬טוביה רוזנברג‪.‬‬
‫תאריך ‪ 7 :‬יולי ‪.2022‬‬
‫זמן ‪ 3 :‬שעות‪.‬‬
‫חומר עזר ‪ :‬אסור‪ .‬המבחן עם חומר סגור‪.‬‬
‫דף נוסחאות ‪ :‬מצורף‪.‬‬

‫הנחיות להגשת הבחינה‪:‬‬


‫ענה בכתב ברור‪,‬קריא ומסודר‪.‬‬ ‫‪.1‬‬
‫ענה על כל השאלות במחברת הבחינה ‪ .‬כולל שאלות הרב‪-‬ברירה (אמריקאי)‪ .‬הטופס הנוכחי‬ ‫‪.2‬‬
‫לא ייבדק‪.‬‬
‫הבחינה ללא חומר עזר‪.‬‬ ‫‪.3‬‬
‫המבחן כתוב בלשון זכר אך פונה לשני המינים כאחד‪.‬‬ ‫‪.4‬‬

‫סה"כ‬ ‫‪13‬‬ ‫‪12‬‬ ‫‪11‬‬ ‫‪10‬‬ ‫‪9‬‬ ‫‪8‬‬ ‫‪7‬‬ ‫‪6‬‬ ‫‪5‬‬ ‫‪4‬‬ ‫‪3‬‬ ‫‪2‬‬ ‫‪:‬שאלה ‪1‬‬
‫‪100‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪2‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪8‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪:‬ניקוד‬

‫‪1‬‬
‫‪2‬‬

‫במערכת תוכנה לפיתוח אפליקציות לטלפונים סלולריים הוחלט להשתמש בתבנית העיצוב(‪)Pattern‬‬ ‫‪.1‬‬
‫‪ .SINGLETON‬המערכת משתמשת ברכיבי אמולטור לטלפונים סלולריים כך שניתן לפתח‬
‫אפליקציות על גבי האמולטור מבלי להזדקק למכשיר הטלפון‪ .‬כל אמולטור (סמסונג ‪,‬שיאומי ‪)...LG ,‬‬
‫הוא אובייקט במערכת המדמה טלפון סלולרי(כמו משחק ‪ Flight Simulator‬המדמה מטוס אמיתי)‪.‬‬
‫המערכת לא מעוניינת ליצור את אותו אובייקט יותר מפעם אחת‪.‬‬
‫כלומר‪ ,‬במידה ונוצר כבר אמולטור מסוג מסויים – לא ניצור אותו שוב אלא נשתמש באובייקט הקיים‪.‬‬
‫לשם כך‪ ,‬מפתחי המערכת עשו התאמה לתבנית העיצוב ‪ SINGLETON‬בהתאם לצרכיהם‪.‬‬
‫לפניך מחלקה (‪ ,CellEmulator )class‬כפי שמהנדסי התוכנה כתבו‪:‬‬

‫{ ‪public class CellEmulator‬‬

‫;‪private static CellEmulator emulator‬‬

‫‪private String cellManufacturer; // Samsung, Xiomi … LG‬‬


‫{ )‪private CellEmulator (String cellManufacturer‬‬
‫;‪this.cellManufacturer = cellManufacturer‬‬
‫}‬

‫} ;)”!‪public void build() { System.out.println(“Built‬‬

‫{ )‪public static CellEmulator getInstance (String cellManufacturer‬‬


‫} ;)‪if (emulator == null) { emulator = new CellEmulator (cellManufacturer‬‬
‫;‪return emulator‬‬
‫}‬
‫}‬

‫‪.‬בודק התוכנה‪ ,‬נוכח לדעת כי קיימת בעיה‪ ,‬והמימוש הנ"ל אינו עונה על הדרישות‬
‫הסבר את הבעיה במימוש הנ"ל‪.‬‬ ‫א‪.‬‬
‫ממש את המחלקה הנ"ל מחדש תוך פתרון הבעיה הנ"ל(יש לכתוב את הקוד של ה – ‪Class‬‬ ‫ב‪.‬‬
‫מחדש)‪.‬‬

‫שים לב‪ ,‬ניקוד יינתן רק עבור פתרון לבעיה הנכונה‪ ,‬ולא באופן רילטבי\יחסי לבעיה שציינת בסעיף א‪.‬‬

‫‪2‬‬
3

:1 ‫פתרון שאלה‬
‫הבעיה במימוש הנ"ל הוא שהיא לא עונה על הדרישה המערכת ליצור אובייקט אחד מכל‬ .‫א‬
‫ נקבל את‬Samsung ‫ ואח"כ את‬Xiomi ‫() את‬getInstance – ‫ אם (לדוגמא) נעביר ל‬.‫אמולטור‬
.Samsung ‫אותו אומלטור\אובייקט בפעם השנייה כשנקרא לפונקציה עם‬
:‫הקוד עם הפתרון‬ .‫ב‬

public class CellEmulator {

private static HashMap<String,CellEmulator> emulators;

private String cellManufacturer; // Samsung, Xiomi … LG

private CellEmulator () { }

public void build() { System.out.println(“Built!”); }

public static CellEmulator getInstance (String cellManufacturer) {

if (emulators== null) { emulators =HashMap<String,CellEmulator>(); }

if (emulators.ContainsKey(cellManufacturer)) {

return emulators.getValue(cellManufacturer);

else{

CellEmulator ce = new CellEmulator();

emulators.add(cellManufacturer,ce);

return ce;

3
4

Interface Segregation Principle(ISP): Solid .2


This principle solves FAT(‫ )שמן‬interface problems of Object-Oriented Programming.

A interface is called FAT when it has too many methods which contains more
information than we really want.

:‫) הסותר את העיקרון לעייל‬Pasudo-Code(‫קוד‬-‫לפניך קוד הכתוב בשיטת פסודו‬

interface Gesture {
func didTap()
func didDoubleTap()
}

class View1 : Gesture {


func didTap() {
//required this method
print(“did the tap”);
}

func didDoubleTap() {
// not required this method
}
}

class View2 : Gesture {


func didTap() {
// not required this method
}
func didDoubleTap() {
//required this method
print(“did the double tap”);
}
}

.)‫ שורות לכול היותר‬2 ‫ ?(תשובה באורך של‬ISP ‫הסבר מדוע הקוד לעייל נוגד את עיקרון‬ .‫א‬
‫ יש לכתוב את הקוד כולו‬.ISP – ‫שנה את הקוד לעייל כך שהוא לא יהיה בניגוד לעיקרון ה‬ .‫ב‬
.)‫קוד‬-‫במחברת הבחינה (בשיטת פסודו‬
– ‫ ? הסבר את ה‬ISP – ‫ מאלו שנלמדו בקורס מדגיש ומרחיב את עיקרון ה‬Pattern ‫איזה‬ .‫ג‬
‫ הסבר‬.‫ שורות‬5 ‫(תשובה באורך של עד‬.ISP – ‫ בקצרה תוך הדגשה על הקשר שלו ל‬Pattern
Pattern-‫ אין קשר ישיר בין ה‬.‫ אין צורך לשרטט דיאגרמה או לכתוב קוד בסעיף זה‬.‫כללי בלבד‬
.)‫לסעיפים הקודמים‬

4
‫‪5‬‬

‫פתרון שאלה ‪:2‬‬


‫מכיוון שה – ‪ interface‬מגדיר פונקציות שכל אחת מהמחלקות הממשות אותו לא‬ ‫א‪.‬‬
‫צריכות אותם אזי ה – ‪ interface‬מוגדר בניגוד לעקרון ה – ‪ ISP‬הדורש ‪ Interface‬רזה\‬
‫מינימלי ככול האפשר‪.‬‬
‫הקוד אחרי התיקון‪:‬‬ ‫ב‪.‬‬

‫{ ‪interface GestureA‬‬

‫)(‪func didTap‬‬

‫}‬

‫{ ‪interface GestureB‬‬

‫)( ‪func didDoubleTap‬‬

‫}‬

‫{ ‪class View1 : GestureA‬‬

‫{ )(‪func didTap‬‬

‫;)”‪print(“did the tap‬‬

‫}‬

‫{ ‪class View2 : GestureB‬‬

‫{ )(‪func didDoubleTap‬‬

‫;)”‪print(“did the double tap‬‬

‫}‬

‫}‬

‫ה ‪ Facade -‬דורש ‪ interface‬רזה שמכיל כמה שפחות פונקציות עם כמה שיותר‬ ‫ג‪.‬‬
‫פרמטרים העונים על דרישת המערכת‪ .‬למשל ‪ interface‬אחד להזמנת חופשה המכיל‬
‫פרמטרים של חופשה‪,‬טיסה ומלון‪.‬‬

‫‪5‬‬
‫‪6‬‬

‫חברת טלדור מפתחת אפליקציה האוספת נתונים ממרכזיית טלפון של שירות לקוחות ואוגרת אותם‬ ‫‪.3‬‬
‫בבסיס נתונים ‪( SQL‬כגון ‪. )SQL Server‬לכול נציג הנכנס למערכת מוקצית שלוחה ממרכזיית‬
‫הטלפון‪.‬‬
‫המערכת מתחברת לשלוחות טלפון רבות ומתעדת את השיחות היוצאות והנכנסות (מס‪ .‬טלפון‬
‫נכנס\יוצא‪ ,‬זמן כניסת השיחה ‪ ,‬אורך השיחה והנציג בשיחה) ‪.‬לכול נציג(‪ )Agent‬הנכנס למערכת ‪,‬‬
‫התוכנה יוצרת ‪ Thread‬המטפל בתיעוד השיחות הנכנסות והיוצאות מהשלוחה של הנציג‪ .‬הנציג יכול‬
‫לבקש מהאפליקציה להקליט את השיחה ואם הוא מקבל את ההרשאה אזי ה – ‪ Thread‬המטפל‬
‫בנציג מקבל הודעה מהאפליקציה שעליו להקליט את השיחה עד סיומה‪ .‬ההרשאה להקליט את‬
‫השיחה ניתנת אך ורק לשיחה מסוימת ולא לכול השיחות של הנציג‪ .‬הצע ‪ Design Pattern‬המתאים‬
‫למימוש תוכנה כזו (התייחס אך ורק לבקשה לתיעוד השיחה וההקלטה שלה‪ .‬התעלם מהאלגוריתם‬
‫המקבל החלטה האם הנציג יכול להקליט או לא את השיחה) ‪.‬‬
‫בתשובתך התייחס למספר הנחות‪:‬‬
‫ישנם נציגים שלא יכולים לבקש כלל הקלטה‪ .‬גם כאן התעלם מהשיקולים אילו נציגים יכולים לבקש‬
‫הקלטה ואילו לא‪ .‬התייחס אך ורק לעובדה שלא לכול הנציגים יש הרשאה להקליט שיחות‪(.‬הסבר‬
‫כללי בלבד על ה – ‪ Pattern‬המתאים [כולל נימוק] עד ‪ 5‬שורות‪ .‬אין צורך לכתוב קוד או לצייר‬
‫דיאגרמה בשאלה זו)‪.‬‬
‫פתרון שאלה ‪:4‬‬
‫‪ DesignPattern‬המתאים לשימוש בקשת תיעוד השיחה של הנציג הוא ה‪ .Observer -‬מכיוון שה‬
‫– ‪ Thread‬נוצר עבור כל נציג והוא צריך לקבל הודעה רק כאשר יש בקשה להקלטה ולא לדגום (‬
‫‪ )POLL‬את המערכת כל הזמן ‪ .‬ה – ‪ Observer‬יעדכן את ה – ‪ Thread‬של הנציג(‪ )Notify‬האם יש‬
‫לו הרשאה להקליט את השיחה או שלא‪ .‬נציג שאין לו הרשאה יקבל עדכון מה – ‪ Subject‬שהוא‬
‫לא יכול להקליט‪.‬‬

‫חברת המשחקים "יצירה" החליטה לפתח מערכת משחקים רב משתתפים למשחקי שחמט‪.‬‬ ‫‪.4‬‬
‫לטובת יצירת המערכת הוגדרו הדרישות הבאות‪:‬‬

‫המערכת צריכה לתמוך בהוספה של שחקנים חדשים‪.‬‬ ‫‪‬‬

‫המערכת צריכה לתמוך בפרישה של שחקנים‪.‬‬ ‫‪‬‬

‫המערכת צריכה לתמוך בהצעת משחקים לזוגות של שחקנים (רצוי שחקנים מאותה רמה)‪.‬‬ ‫‪‬‬

‫‪6‬‬
‫‪7‬‬

‫המערכת תתעד עבור כל שחקן את היסטרית המשחקים כולל מספר הניצחונות וההפסדים ‪.‬‬ ‫‪‬‬

‫המערכת מאפשרת למנהל לראות דוחות סטטיסטיקת שימוש שונות באתר ‪.‬‬ ‫‪‬‬

‫שרטט דיאגרמת ‪ USE-CASE‬לפי הכללים והסימונים שלמדנו‪.‬‬

‫ענה על השאלות הבאות ‪:‬‬ ‫‪.5‬‬

‫‪7‬‬
8

? Abstract Factory – ‫ ו‬Patterns : Factory – ‫הסבר את ההבדל העיקרי בין שני ה‬ .‫א‬
‫ אין צורך בסעיף זה לרשום קוד או לשרטט‬.)‫ הסבר כללי בלבד‬.‫ שורות בלבד לכול היותר‬2(
.‫דיאגרמה‬
‫ או‬Factory ‫ של‬Pattern – ‫ענה (הסבר ונימוק) האם הקוד הרשום בסעיף ג תואם ל‬ .‫ב‬
)‫ שורות בלבד‬2 ‫ ?(לרשותך‬Abstract Factory
‫ יש להשלים אותו על מנת שיעבוד בהתאם לתשובה שענית בסעיף‬JAVA – ‫לפניך קוד ב‬ .‫ג‬
\‫ יש להעתיק למחברת הבחינה רק את השינויים‬.‫ תקן את הקוד במחברת הבחינה‬.‫הקודם‬
.‫ים‬Class – ‫ משתנים ו‬,‫ מותר להוסיף\לשנות\למחוק פונקציות\מתודות‬.‫תוספות שביצעת‬

abstract class AbstractProductA{


public abstract void operationA1();
public abstract void operationA2();
}

class ProductA extends AbstractProductA {


ProductA(String arg){
System.out.println("Hello "+arg);
}
public void operationA1() {
};
public void operationA1() {
};
}

abstract class AbstractProductB {


public abstract void operationB1();
public abstract void operationB2();
}

class ProductB extends AbstractProductB{


ProductB(String arg){
System.out.println("Hello "+arg);
}
public void operationB1() {
};
public void operationB1() {
};
}
abstract class AbstractFactory{
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();

8
9

class ConcreteFactoryA extends AbstractFactory{


AbstractProductA createProductA(){
return new AbstractProductA ("AbstractProductA");
}

class ConcreteFactoryB extends AbstractFactory{


AbstractProductB createProductB(){
return new AbstractProductB ("AbstractProductB");
}
}

//Factory creator - an indirect way of instantiating the factories


class FactoryMaker{
private static AbstractFactory pf=null;
static AbstractFactory getFactory(String choice){
if(choice.equals("a")){
pf=new ConcreteFactoryA();
}else if(choice.equals("b")){
pf=new ConcreteFactoryB();
}
return pf;
}
}

// Client
public class Client{
public static void main(String args[]){
AbstractFactory pf=FactoryMaker.getFactory("a");
AbstractProductA product=pf.createProductA();
//more function calls on product
}
}

Class -‫ים לעייל(אחרי התיקונים שביצעת בסעיף הקודם) ב‬Class -‫הצג את הקוד של ה‬ .‫ד‬
.‫ במחברת הבחינה‬Diagram
:5 ‫פתרון שאלה‬

9
10

‫ תוך מימוש אלגוריתם‬, ‫ המייצר אובייקטים מטיפוס אחד‬Pattern ‫ (מפעל) הוא‬Factory .‫א‬
‫ הוא למעשה‬Abstract Factory .‫כלשהו המגביל את כמות האובייקטים שהמערכת מייצר‬
‫ כלומר מפעל של מפעלים שכל אחד מהם מחליט על כמות‬, Factory ‫ של‬Factories
.‫האובייקטים שהמערכת מייצרת מטיפוס כלשהו‬
.Abstract Factory – ‫ ולכן מדובר ב‬Factories ‫הקוד עושה שימוש בכמה‬ .‫ב‬
:‫פתרון הקוד‬ .‫ג‬
abstract class AbstractProductA{
public abstract void operationA1();
public abstract void operationA2();
}

class ProductA extends AbstractProductA {


ProductA(String arg){
System.out.println("Hello "+arg);
}
public void operationA1() {
};
public void operationA2() {
};
}

abstract class AbstractProductB {


public abstract void operationB1();
public abstract void operationB2();
}
class ProductB extends AbstractProductB{
ProductB(String arg){
System.out.println("Hello "+arg);
}
public void operationB1() {
};
public void operationB2() {
};
}
abstract class AbstractFactory{
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();
}

class ConcreteFactoryA extends AbstractFactory{


AbstractProductA createProductA(){
return new ProductA ("ProductA");
}
class ConcreteFactoryB extends AbstractFactory{

10
11

AbstractProductB createProductB(){
return new ProductB("ProductB");
}
}
//Factory creator - an indirect way of instantiating the
factories
class FactoryMaker{
private static AbstractFactory pf=null;
static AbstractFactory getFactory(String choice){
if(choice.equals("a")){
pf=new ConcreteFactoryA();
}else if(choice.equals("b")){
pf=new ConcreteFactoryB();
}
return pf;
}
}
// Client
public class Client{
public static void main(String args[]){
AbstractFactory pf=FactoryMaker.getFactory("a");
AbstractProductA product=pf.createProductA();
//more function calls on product
}
}

11
‫‪12‬‬

‫ד‪.‬‬

‫א‪ .‬מה משמעות ה – ‪ Annotation‬של @‪ test‬ב – ‪( ? Junit‬תשובה באורך של ‪ 2‬שורות בלבד‬ ‫‪.6‬‬
‫במחברת הבחינה‪ .‬הסבר כללי בלבד)‪.‬‬
‫האם ה – ‪ Annotation‬יכולה לחזור על עצמה ב – ‪ ? Class‬יש לנמק את תשובתך‪( .‬תשובה‬ ‫ב‪.‬‬
‫באורך של שורה אחת בלבד)‪.‬‬
‫מה היתרון של בדיקת קוד באמצעות ספריות ‪ JUNIT‬על פני בדיקת קוד שכתוב ב‪?MAIN -‬‬ ‫ג‪.‬‬
‫הסבר ונמק‪( .‬תשובה כללית בלבד באורך של ‪ 3‬שורות לכול היותר)‪.‬‬
‫מה הם ארבעת שלבי הבדיקות ? פרט את השלבים ואת המשמעות של כל שלב‪(.‬תשובה‬ ‫ד‪.‬‬
‫באורך של ‪ 5‬שורות בלבד לכול היותר)‪.‬‬
‫נניח ואתה מבצע שינוי קטן במערכת (למשל הוספת שדה בטופס) ועליך לבדוק את השינוי הזה‬ ‫ה‪.‬‬
‫באיזה שלב בבדיקות השינוי הזה ייבדק? (תשובה באורך של ‪ 5‬שורות לכול היותר)‪.‬‬

‫פתרון שאלה ‪:6‬‬

‫כל @‪ test‬הוא ‪ UnitTest‬שרץ באופן עצמאי ומבצע בדיקה כלשהי על פונקציה שקיימת בתוכנה‪.‬‬ ‫א‪.‬‬
‫בוודאי‪ .‬יכולים להיות מספר ‪test‬ים באותו ‪ Class‬שמבצעים בדיקות שונות‪.‬‬ ‫ב‪.‬‬

‫‪12‬‬
‫‪13‬‬

‫‪ JUNIT‬הוא ממש ‪ FrameWork‬המקנה ספריות ומתודות השוואה ‪ BuiltIN‬ובאמצעותם קל לממש‬ ‫ג‪.‬‬


‫בדיקות יחידה‪ .‬כל ‪ test‬הוא יחידה נפרדת שאינה תלויה בשאר ה – ‪test‬ים ובודקת פונקציונליות‬
‫כלשהי במערכת‪ .‬ניתן גם לבצע לפני ואחרי כל ‪ test‬הרצת קוד כלשהו וגם לפני ואחרי כל ה –‬
‫‪test‬ים‪.‬‬
‫‪ – UnitTest‬בדיקות יחידה על הפונקציונליות שנוספה למערכת‪.‬‬ ‫ד‪.‬‬
‫‪ – IntegrationTest‬בדיקות של כל המודול\ספרייה שנוספה למערכת כחלק מהמערכת‪.‬‬
‫‪ – System‬בדיקות של על מערכת התוכנה ‪ ,‬כולל תקשורת‪ ,‬חומרה ובסיס נתונים‪.‬‬
‫‪\AT‬ייצור – בדיקות מסירת המערכת ללקוח הכוללת את הפונקציות העיקריות במערכת‪.‬‬
‫כבר משלב הפיתוח ‪ ,‬ברגע שהשינוי בוצע ‪ ,‬יש לבדוק את השינוי בתוכנה בבדיקות יחידה ואחר כך‬ ‫ה‪.‬‬
‫את כל השלבים לפי התיאור בסעיף הקודם‪.‬‬

‫לפניך ‪Class‬הכתוב בפסאודו–קוד‪.‬‬ ‫‪.7‬‬


‫ציין מה הבעיה במערכת עם מימוש של ‪ Class‬כזה ואיזה עקרון הוא סותר ב – ‪ ? SOLID‬התייחס‬ ‫א‪.‬‬
‫בתשובתך למושג ‪(Cohesion‬התלכדות)‪.‬‬
‫{ ‪Class A‬‬
‫;)‪multiply(int a,int b‬‬
‫;)(‪void checkEmailInfo‬‬
‫;)‪void sendEmail(String address‬‬
‫;)(‪void removeEmail‬‬
‫;)‪add(int a,int b,int c‬‬
‫}‬
‫הראה(יש לכתוב קוד) כיצד ניתן היה נכון יותר לממש את ה‪ Class -‬בצורה אחרת‪ .‬ניתן להוסיף\‬ ‫ב‪.‬‬
‫למחוק\לשנות פונקציות\מתודות ו\או ‪Class‬ים‪.‬‬
‫פתרון שאלה ‪:7‬‬
‫ה – ‪ Class‬הנתון נוגד את העיקרון הראשון(‪ )SRP‬של ה – ‪ Solid‬אשר טוען שלכל ‪Class‬‬ ‫א‪.‬‬
‫יש תפקיד אחד ויחיד וגם מטרה אחת ויחידה‪ .‬ה – ‪ Class‬לעייל גם מטפל בהודעות‬
‫מייל וגם בחישובים אריתמטיים‪.‬‬
‫הפתרון הוא הפרדה לשני ‪Class‬ים‪:‬‬ ‫ב‪.‬‬
‫{ ‪Class MAILHANDLE‬‬

‫;)(‪void checkEmailInfo‬‬

‫;)‪void sendEmail(String address‬‬

‫;)(‪void removeEmail‬‬

‫}‬

‫‪13‬‬
14

Class MATH {

multiply(int a,int b);

add(int a,int b,int c);

)‫ (יש להעתיק את התשובה הנכונה למחברת הבחינה‬:‫בעלי ענין במערכת כוללים‬ .8


.‫כל אדם או ארגון שיש לו עניין במערכת המפותחת‬ .‫א‬
.‫משתמשים צפויים במערכת המפותחת‬ .‫ב‬
.‫גורמים המממנים את הפיתוח‬ .‫ג‬
.‫גורמים חיצוניים שמושפעים ישירות מהמערכת המפותחת‬ .‫ד‬

9. LSP (LISKOV Substitution Principle from SOLID) : Objects should be replaceable with their
subtypes without affecting the correctness of the program.

:)‫(ריבוע‬Square – ‫(מלבן) ו‬Rectangle ‫ המיישם‬Class ‫לפניך‬


public class Rectangle{
private int height;
private int width;

public void setHeight(int newHeight) {


this.height = newHeight;
}

public void setWidth(int newWidth) {


this.width = newWidth;
}

public int getWidth() {


return width;
}

public int getHeight(){


return height;
}
}

public class Square extends Rectangle {

@Override
public void setHeight(int height) {
super.setHeight(height);
}

14
‫‪15‬‬

‫‪@Override‬‬
‫{ )‪public void setWidth(int width‬‬
‫;)‪super.setWidth(width‬‬
‫}‬
‫}‬

‫הסבר מדוע הקוד של ה – ‪ Square‬לעייל בעייתי ?(‪ 4‬שורות לכול היותר‪ .‬הסבר כללי בלבד)‬ ‫א‪.‬‬
‫הצע פתרון לסעיף הקודם תוך שינוי(בלבד) בקוד של ה – ‪ Square‬בלבד‪ .‬אין להוסיף ‪Class‬ים‬ ‫ב‪.‬‬
‫חדשים ואין להוסיף פונקציות\מתודות חדשות‪ .‬יש להעתיק למחברת הבחינה את ה – ‪Square‬‬
‫‪ Class‬כולל השינויים שלך‪.‬‬
‫הסבר מדוע הקוד הנ"ל(כולל הפתרון בסעיף הקודם) סותר את עיקרון ה – ‪ LSP‬מה‪.SOLID -‬‬ ‫ג‪.‬‬
‫הצע פתרון שיענה על העיקרון ה – ‪ .LSP‬הצעת הפתרון יכולה להיות הסבר כללי או ‪Class‬‬
‫‪ .Diagram‬בהצעת הפתרון אין צורך לציין פונקציות או משתנים‪.‬‬
‫פתרון שאלה ‪:9‬‬
‫הקוד בעייתי מכיוון שניתן לקרוא לפונקציית ‪ setWidth‬או לפונקציית ‪ setHeight‬בנפרד ואז‬ ‫א‪.‬‬
‫נקבל צורה בה הצלעות לא שוות ‪ ,‬מה שכמובן סותר גיאומטרית את מבנה הריבוע‪.‬‬
‫קוד‪:‬‬ ‫ב‪.‬‬
‫{ ‪public class Square extends Rectangle‬‬

‫‪@Override‬‬
‫{ )‪public void setHeight(int height‬‬
‫;)‪super.setHeight(height‬‬
‫;)‪super.setWidth(height‬‬
‫}‬

‫‪@Override‬‬
‫{ )‪public void setWidth(int width‬‬
‫)‪super.setWidth(width‬‬
‫;)‪super.setHeight(height‬‬
‫}‬
‫הקוד סותר את העיקרון של ‪ LSP‬כי העיקרון קובע שניתן להחליף כל ‪ Derived Class‬ב‪-‬‬ ‫ג‪.‬‬
‫‪ Base Class‬מבלי לשנות את הקוד (למעט ההחלפה) והתוכנה תרוץ כמו לפני השינוי‪.‬‬
‫במקרה לעייל ‪ Square‬הוא איננו סוג של ‪ Rectangle‬ולכן החלפה כזו לא אפשרית‬
‫בתוכנה וזה בניגוד לעיקרון ‪ LSP‬מה – ‪.SOLID‬‬

‫‪Integer,Double,Float‬‬ ‫‪.10‬‬
‫הם ‪Class‬ים המאפשרים לשמור ערכים מספריים\נומריים באובייקטים‪ .‬לדוגמא הקוד הבא ‪:‬‬

‫‪15‬‬
‫‪16‬‬

‫‪Float f1‬‬ ‫;‪= 2.2‬‬


‫‪Double d1‬‬ ‫;‪= 1.1‬‬
‫;‪Integer i1 = 9‬‬
‫הסבר מדוע יש צורך ב‪Class -‬ים האלה כאשר בשפה מוגדרים הטיפוסים הפרמיטיביים\‬ ‫א‪.‬‬
‫סטנדרטיים ‪(? float/double/int‬תשובה באורך של ‪ 3‬שורות בלבד לכול היותר)‬
‫באיזה ‪ Pattern‬ה – ‪Class‬ים האלה (‪ )Integer,Double,Float‬משתמשים ? הסבר‪,‬נמק ופרט (‪3‬‬ ‫ב‪.‬‬
‫שורות בלבד)‪.‬אין צורך בסעיף זה לכתוב קוד או לצייר דיאגרמה‪.‬‬
‫פתרון שאלה ‪:10‬‬
‫יש צורך ב – ‪Class‬ים האלה מכיוון שאם אנחנו רוצים לייצר רשימה או מפה (‬ ‫א‪.‬‬
‫‪ )HashMap/List‬של מספרים‪ ,‬אנחנו צריכים להשתמש באובייקטים ממש והטיפוסים‬
‫הפרימיטיביים אינם אובייקטים‪.‬‬
‫‪ – Wrapper‬הוא עוטף את הטיפוסים הפרימיטיביים וכך יכול לספק פונקציונליות‬ ‫ב‪.‬‬
‫נוספת כמו לחשב ערך ‪ HASH‬עבור מספרים שלמים(‪.)Integer‬‬

‫מפעל לייצור לוויינים(‪ )Satellite‬של התעשייה האווירית החליט להוציא החוצה את ייצור המשגר‬ ‫‪.11‬‬
‫למפעל חיצוני‪ .‬זכית במכרז ונבחרת לבצע את המשימה של ייצור המשגר‪ .‬עליך לכתוב מערכת‬
‫שתממש את פעולת המשגר‪ .‬הדרישה המרכזית היא שהמשגר יתמוך ב – ‪ 2‬פעולות מרכזיות‪.‬‬
‫לחצן ראשון ‪ :‬הפעלת מבערים‪ .‬לחצן שני ‪ :‬שיגור‪.‬‬
‫ממש את המערכת בשפת ‪ JAVA‬או ב – ‪ ++C‬תוך שימוש ב – ‪ Pattern‬המתאים ביותר‬ ‫א‪.‬‬
‫למשימה מבין אלו שלמדנו‪ .‬על הקוד להכיל בין היתר את המחלקות ‪Launch , Burner :‬‬
‫ואת פונקציית ‪.MAIN‬‬
‫כתוב בבירור את שם התבנית(‪ )Pattern‬שבחרת ושרטט ‪ Class Diagram‬המתאים למימוש‬ ‫ב‪.‬‬
‫שלך‪.‬‬

‫פתרון שאלה ‪:11‬‬


‫סעיף א‪.‬‬
‫{ ‪public interface ActionListenerCommand‬‬
‫;)(‪public void execute‬‬
‫}‬
‫{‪public class ActionBurner implements ActionListenerCommand‬‬

‫‪16‬‬
17

private Missile mis;


public ActionBurner(Missile mis) {
this.mis = mis;
}
@Override
public void execute() {
mis.burner();
}
}
public class ActionLaunch implements ActionListenerCommand{

private Missile mis;

public ActionLaunch(Missile mis) {


this.mis = mis;
}
@Override
public void execute() {
mis.launch();
}
}
public class Missile {
public Missele() {
}

public void burner(){


System.out.println("Burner");
}

17
18

public void launch() {


System.out.println("Launch");
}
}
public class MenuOptions {
private ActionListenerCommand launchCommand;
private ActionListenerCommand burnerCommand;

public MenuOptions(ActionListenerCommand ActionBurner,


ActionListenerCommand ActionLaunch) {
this.launchCommand = ActionLaunch;
this.burnerCommand = ActionBurner;
}
public void clickLaunch(){
launchCommand.execute();
}
public void clickBurner(){
burnerCommand.execute();
}
}
public class CommandPatternClient {
public static void main(String[] args) {
Document missile = new Missile();

ActionListenerCommand clickBurner = new ActionBurner(missile);


ActionListenerCommand clickLaunch = new ActionLaunch(missile);
MenuOptions menu = new MenuOptions(clickBurner, clickLaunch);
menu.clickBurner();
menu.clickLaunch();

18
‫‪19‬‬

‫}‬
‫}‬
‫סעיף ב‪:‬‬

‫משרד התחבורה מתכנן רשת כבישים חדשה שתשרת את העיר החדשה הנבנית בימים אלה‪ ,‬עיר‬ ‫‪.12‬‬
‫הימים‪ .‬כדי לסמלץ\לדמות את עומסי התנועה באזור יש להציג את הרכבים על המפה‪ .‬המערכת‬
‫תומכת ב‪ 2-‬סוגי רכבים ‪ :‬מכוניות ומשאיות‪ .‬המתכנת כתב את הקוד הבא ‪:‬‬
‫;)(>‪ArrayList<Vehicle> vehiclesList = new ArrayList<Vehicle‬‬

‫{ )(‪private static void createRandomCar‬‬


‫;)(‪Random random = new Random‬‬

‫‪19‬‬
‫‪20‬‬

‫;)‪int randInt = random.nextInt(2‬‬


‫;‪Vehicle vehicle = null‬‬
‫{ )‪if(randInt == 0‬‬
‫;)(‪vehicle = new Car‬‬
‫{ )‪} else if(randInt == 1‬‬
‫;)(‪vehicle = new Truck‬‬
‫}‬
‫;))‪vehicle.setLocation(random.nextInt(1000), random.nextInt(1000‬‬
‫;)‪vehiclesList.add(vehicle‬‬
‫}‬

‫הסבר את הבעייתיות בקוד לעייל ?(‪ 3‬שורות לכול היותר‪ .‬הסבר כללי בלבד)‪ .‬אין צורך בסעיף זה‬ ‫א‪.‬‬
‫לכתוב קוד או לשרטט דיאגרמה‪.‬‬
‫הצע פתרון חלופי תוך הסתמכות על אחד מהתבניות (‪ )Design Pattern‬שלמדנו בקורס ‪ .‬הסבר‬ ‫ב‪.‬‬
‫מדוע ה – ‪ Pattern‬פותר את הבעייתיות שכתבת בסעיף הקודם‪ .‬אין צורך לכתוב את הקוד מחדש‬
‫לעייל או לשנות אותו‪.‬‬

‫פתרון שאלה ‪:12‬‬


‫הקוד בדוגמא לעייל יווצר בכל פעם מכונית או משאית חדשה למרות שהוא איננו משתמש‬ ‫א‪.‬‬
‫באובייקט‪ ,‬אלא‪ ,‬אך ורק בסימון שלו על המפה‪ .‬מימוש זה הוא בזבזני מבחינת צריכה‬
‫הזיכרון ויכול בהחלט להוביל לחריגה – ‪.OutOfMemory Exception‬‬
‫נשתמש ב – ‪ . FlyWeight Pattern‬ה – ‪ Pattern‬דורש להשתמש בכול פעם באותו אובייקט וכך‬ ‫ב‪.‬‬
‫התוכנית תשתמש בזיכרון בצורה יעילה הרבה יותר‪ .‬התוכנית תציב את אותה משאית\מכונית בכול‬
‫פעם במיקום אחר על המפה ולא תיצור מכונית\משאית חדשה בכול פעם שיש למקם כלי רכב על‬
‫המפה‪.‬‬

‫להלן קוד העושה שימוש ב – ‪ Abstract Factory‬ומצייר צורות על המסך(הקוד נלמד באחד‬ ‫‪.13‬‬
‫מהשיעורים בקורס) ‪:‬‬
‫;)‪AbstractFactory shapeFactory=FactoryProducer.getFactory(false‬‬
‫;)"‪Shape shape1 = shapeFactory.getShape("RECTANGLE‬‬
‫;)(‪shape1.draw‬‬
‫;)"‪Shape shape2 = shapeFactory.getShape("SQUARE‬‬
‫;)(‪shape2.draw‬‬
‫;)‪AbstractFactory roundedShapeFactory=FactoryProducer.getFactory(true‬‬
‫;)"‪Shape shape3 = roundedShapeFactory.getShape("ROUNDED_RECTANGLE‬‬
‫;)(‪shape3.draw‬‬
‫;)"‪Shape shape4 = roundedShapeFactory.getShape("ROUNDED_SQUARE‬‬
‫;)(‪shape4.draw‬‬

‫‪20‬‬
‫‪21‬‬

‫הפרמטר ‪ true/false‬בפונקציית ‪ getFactory‬קובע האם ה ‪ Factory -‬יוצר צורות מעוגלות (‬ ‫‪-‬‬


‫‪ )rounded‬או רגילות‪.‬‬

‫הקוד לא תומך בפעולת ‪ . UNDO‬הצע שיפור לקוד לעייל תוך הסתמכות על אחד מה –‬ ‫א‪.‬‬
‫‪ Patterns‬שנלמדו בקורס כדי שיתמוך ב‪( .UNDO -‬הסבר כללי בלבד על ה – ‪Pattern‬‬
‫המתאים‪ 3 .‬שורות לכול היותר)‪ .‬אין צורך בסעיף זה לכתוב קוד או לשרטט דיאגרמה‪.‬‬
‫יש לכתוב קוד ב – ‪ JAVA‬תוך הסתמכות על ה – ‪ Pattern‬מהסעיף הקודם המאפשר לבצע את‬ ‫ב‪.‬‬
‫פעולת ה – ‪ .UNDO‬אין מגבלה על הוספה(או שינוי) ‪ Class/Methods/Variables‬בסעיף זה‪.‬‬
‫יש לשנות את הקוד לעייל כך שיעשה שימוש ב – ‪( UNDO‬ניתן לבחור בפקודת ‪ UNDO‬בכול‬ ‫ג‪.‬‬
‫מקום בקוד לעייל‪ .‬מקום הקריאה ל – ‪ UNDO‬נתון לבחירתך‪ .‬ניתן לקרוא ל – ‪ UNDO‬יותר‬
‫מפעם אחת)‪ .‬רשום במחברת הבחינה את הקוד לעייל (כולו) כולל השינויים שלך‪.‬‬
‫פתרון שאלה ‪:13‬‬
‫שימוש ב – ‪ Pattern‬של ‪ Momento‬יפתור את הבעיה של תמיכה ביכולת ‪.UNDO‬‬ ‫א‪.‬‬
‫הקוד‪:‬‬ ‫ב‪.‬‬

‫{ ‪public interface Shape‬‬


‫;)(‪void draw‬‬
‫;)(‪void clear‬‬
‫}‬
‫{ ‪public class Memento‬‬

‫;‪private Shape state‬‬

‫{ )(‪public Memento‬‬
‫;‪this.state = null‬‬
‫}‬

‫{ )(‪public Shape getState‬‬


‫;‪return state‬‬
‫}‬

‫{ )‪public void setState(Shape state‬‬


‫;‪this.state = state‬‬
‫}‬
‫}‬
‫{ ‪public class Canvas‬‬

‫;‪private Shape shape=null‬‬


‫;)(‪private Memento memento = new Memento‬‬

‫‪21‬‬
22

public void write(Shape shape) {


this.shape = shape;
}

public void save() {


memento.setState(shape);
}

public void undo() {


shape = memento.getState();
shape.clear();
}
}

Main -‫ה‬ .‫ג‬


public class DocumentViewer {

private static Canvas cv = new Canvas();

public static void main(String[] args) {


AbstractFactory shapeFactory=FactoryProducer.getFactory(false);
Shape shape1 = shapeFactory.getShape("RECTANGLE");
cv.write(shape1);
cv.save();
shape1.draw();
cv.undo();
Shape shape2 = shapeFactory.getShape("SQUARE");
shape2.draw();
AbstractFactory
roundedShapeFactory=FactoryProducer.getFactory(true);
Shape shape3 = roundedShapeFactory.getShape("ROUNDED_RECTANGLE");
shape3.draw();
Shape shape4 = roundedShapeFactory.getShape("ROUNDED_SQUARE");
shape4.draw();
}
}
! ‫בהצלחה‬

22

You might also like