כיצד להחליף רבים אם הצהרות ב- Java

1. סקירה כללית

מבני החלטות הם חלק חיוני בכל שפת תכנות. אך אנו נקבעים בקידוד מספר עצום של הצהרות מקוננות שהופכות את הקוד שלנו למורכב וקשה יותר לתחזוקה.

במדריך זה, נלך דרך ה- דרכים שונות להחלפת הצהרות מקוננות אם.

בואו נבדוק אפשרויות שונות כיצד נוכל לפשט את הקוד.

2. מקרה מבחן

לעיתים קרובות אנו נתקלים בהיגיון עסקי הכרוך בהרבה תנאים, וכל אחד מהם זקוק לעיבוד שונה. לצורך הדגמה, ניקח לדוגמא א מַחשְׁבוֹן מעמד. תהיה לנו שיטה שלוקחת שני מספרים ומפעיל כקלט ומחזיר את התוצאה בהתבסס על הפעולה:

חישוב int ציבורי (int a, int b, מחרוזת מחרוזת) {int result = Integer.MIN_VALUE; אם ("הוסף". equals (operator)) {result = a + b; } אחר אם ("הכפל". שווה (אופרטור)) {תוצאה = a * ב; } אחר אם ("חלק". שווה (אופרטור)) {תוצאה = a / b; } אחר אם ("לחסר". שווה (אופרטור)) {תוצאה = א - ב; } להחזיר תוצאה; }

אנו יכולים גם ליישם זאת באמצעות החלף הצהרות:

public int calcuUsingSwitch (int a, int b, מחרוזת מחרוזת) {switch (operator) {case "add": result = a + b; לשבור; // מקרים אחרים} החזרת תוצאה; }

בהתפתחות אופיינית, הצהרות ה- if עשויות להיות הרבה יותר גדולות ומורכבות באופיין. גַם, הצהרות המתג אינן מתאימות היטב כשיש תנאים מורכבים.

תופעת לוואי נוספת של בניית החלטות מקוננות היא שהן הופכות לבלתי ניתנות לניהול. לדוגמא, אם עלינו להוסיף אופרטור חדש, עלינו להוסיף משפט if אם וליישם את הפעולה.

3. שיקום מחדש

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

3.1. מחלקת מפעל

פעמים רבות אנו נתקלים במבני החלטות שבסופו של דבר מבצעים פעולה דומה בכל ענף. זה מספק הזדמנות ל לחלץ שיטת מפעל המחזירה אובייקט מסוג מסוים ומבצעת את הפעולה על סמך התנהגות האובייקט הקונקרטית.

לדוגמא שלנו, בואו נגדיר מבצע ממשק שיש בו יחיד להגיש מועמדות שיטה:

ממשק ציבורי מבצע {int להחיל (int a, int b); }

השיטה לוקחת שני מספרים כקלט ומחזירה את התוצאה. בואו נגדיר כיתה לביצוע תוספות:

מחלקה ציבורית מיישמת תוספת פעולה {@Override public int להחיל (int a, int b) {להחזיר a + b; }}

כעת נבצע מחלקת מפעל המחזירה מקרים של מבצע בהתבסס על המפעיל הנתון:

מחלקה ציבורית OperatorFactory {operationMap Map Map = חדש HashMap (); סטטי {operationMap.put ("הוסף", תוספת חדשה ()); operationMap.put ("לחלק", חטיבה חדשה ()); // עוד אופרטורים} סטטי ציבורי אופציונלי getOperation (מחרוזת מחרוזת) {return Optional.ofNullable (operationMap.get (operator)); }}

עכשיו, ב מַחשְׁבוֹן בכיתה, אנו יכולים לשאול את המפעל כדי לקבל את הפעולה הרלוונטית ולהחיל על מספרי המקור:

public int calcuUsingFactory (int a, int b, מחרוזת מחרוזת) {Operation targetOperation = OperatorFactory .getOperation (operator) .orElseThrow (() -> IllegalArgumentException חדש ("מפעיל לא חוקי")); return targetOperation.apply (a, b); }

בדוגמה זו ראינו כיצד האחריות מוסמכת על אובייקטים משולבים באופן רופף המוגשים על ידי מעמד מפעל. אך יתכן שיש סיכויים שמקוננים אם ההצהרות פשוט מועברות למחלקת המפעלים שמביסה את מטרתנו.

לחלופין, אנו יכולים לשמור על מאגר של אובייקטים ב- מַפָּה שניתן לשאול לבדיקה מהירה. כפי שראינו OperatorFactory # operationMap משרת את מטרתנו. אנחנו יכולים לאתחל מַפָּה בזמן ריצה והגדר אותם לחיפוש.

3.2. שימוש ב- Enums

בנוסף לשימוש ב- מַפָּה, אנחנו יכולים גם להשתמש Enum לתייג לוגיקה עסקית מסוימת. לאחר מכן, אנו יכולים להשתמש בהם בקינון אם הצהרות אוֹ מקרה מתגהצהרות. לחלופין, אנו יכולים להשתמש בהם גם כמפעל של חפצים ולבצע אסטרטגיה שלהם לביצוע ההיגיון העסקי הקשור.

זה יפחית את מספר המקוננים אם גם הצהרות ויאציל את האחריות ליחיד Enum ערכים.

בואו נראה איך נוכל להשיג את זה. בהתחלה, עלינו להגדיר את שלנו Enum:

מפעיל אנומטי ציבורי {ADD, MULTIPLY, SUBTRACT, DIVIDE}

כפי שניתן לראות, הערכים הם התוויות של המפעילים השונים אשר ישמשו עוד לחישוב. תמיד יש לנו אפשרות להשתמש בערכים כתנאים שונים בקינון אם הצהרות או החלפת מקרים, אבל בואו נתכנן דרך חלופית להאציל את הלוגיקה ל Enum את עצמה.

נגדיר שיטות לכל אחת מה- Enum ערכים ועשו את החישוב. לדוגמה:

הוסף {@Override public int להחיל (int a, int b) {להחזיר a + b; }}, // מפעילים אחרים public abstract int להחיל (int a, int b);

ואז ב מַחשְׁבוֹן בכיתה, אנו יכולים להגדיר שיטה לביצוע הפעולה:

public int חישוב (int a, int b, מפעיל מפעיל) {return operator.apply (a, b); }

כעת אנו יכולים להפעיל את השיטה באמצעות להמיר את חוּט ערך ל- מַפעִיל באמצעות Operator # valueOf () שיטה:

@ מבחן ציבורי בטל whenCalculateUsingEnumOperator_thenReturnCorrectResult () {מחשבון מחשבון = מחשבון חדש (); int result = calculator.calculate (3, 4, Operator.valueOf ("ADD")); assertEquals (7, תוצאה); }

3.3. תבנית פיקוד

בדיון הקודם ראינו שימוש במחלקת מפעל להחזרת המופע של האובייקט העסקי הנכון עבור המפעיל הנתון. מאוחר יותר, האובייקט העסקי משמש לביצוע החישוב ב- מַחשְׁבוֹן.

אנחנו יכולים גם לעצב מחשבון # חשב שיטה לקבל פקודה שניתן לבצע על הקלטים. זו תהיה דרך נוספת להחלפה מקוננת אם הצהרות.

נגדיר תחילה את שלנו פקודה מִמְשָׁק:

ממשק ציבורי פיקוד {ביצוע שלם (); }

לאחר מכן, בוא ניישם הוסף פקודה:

המחלקה הציבורית AddCommand מיישם את הפקודה {// משתני מופע public AddCommand (int a, int b) {this.a = a; this.b = b; } @Override שלם ציבורי לבצע () {להחזיר a + b; }}

לבסוף, בואו נציג שיטה חדשה ב- מַחשְׁבוֹן שמקבל ומבצע את פקודה:

public int חישוב (Command command) {return command.execute (); }

לאחר מכן נוכל להפעיל את החישוב על ידי הפעלת מיידית של AddCommand ולשלוח אותו אל מחשבון # חשב שיטה:

@Test ציבורי בטל כאשרCalculateUsingCommand_thenReturnCorrectResult () {מחשבון מחשבון = מחשבון חדש (); int result = calculator.calculate (חדש AddCommand (3, 7)); assertEquals (10, תוצאה); }

3.4. מנוע כלל

כאשר בסופו של דבר אנו כותבים מספר רב של הצהרות מקוננות אם, כל אחד מהתנאים מתאר כלל עסקי שיש להעריך בכדי לעבד את ההיגיון הנכון. מנוע כלל מביא מורכבות כזו מהקוד הראשי. א RuleEngine מעריך את כללים ומחזירה את התוצאה על סמך הקלט.

בואו נעבור דוגמה על ידי תכנון פשוט RuleEngine שמעבד ביטוי דרך סט של כללים ומחזירה את התוצאה מהנבחר כְּלָל. ראשית נגדיר א כְּלָל מִמְשָׁק:

ממשק ציבורי כלל {הערכה בוליאנית (ביטוי ביטוי); תוצאה getResult (); }

שנית, בואו ליישם א RuleEngine:

class class RuleEngine {כללי רשימה סטטית פרטית = ArrayList חדש (); סטטי {rules.add (AddRule חדש ()); } תהליך תוצאה ציבורי (ביטוי ביטוי) {כלל כלל = כללים .stream () .filter (r -> r.evaluate (expression)) .findFirst () .orElseThrow (() -> IllegalArgumentException חדש ("הביטוי אינו תואם אף אחד כְּלָל")); return return.getResult (); }}

ה RuleEngine מקבל ביטוי מתנגד ומחזיר את תוֹצָאָה. עַכשָׁיו, בואו נעצב את ביטוי כיתה כקבוצה של שניים מספר שלם חפצים עם מַפעִיל אשר יוחל:

ביטוי בכיתה ציבורית {שלם פרטי פרטי x; שלם פרטי y; מפעיל מפעיל פרטי; }

ולבסוף בואו נגדיר מנהג AddRule כיתה שמעריכה רק מתי מבצע הוספה מוגדר:

מחלקה ציבורית AddRule מיישם כלל {@Override ציבור בוליאני הערכה (ביטוי ביטוי) {בוליאני evalResult = false; אם (expression.getOperator () == Operator.ADD) {this.result = expression.getX () + expression.getY (); evalResult = נכון; } להחזיר evalResult; }}

כעת נפעיל את RuleEngine עם ביטוי:

@Test הציבור בטל כאשרNumbersGivenToRuleEngine_thenReturnCorrectResult () {ביטוי ביטוי = ביטוי חדש (5, 5, Operator.ADD); מנוע RuleEngine = RuleEngine חדש (); תוצאת תוצאה = engine.process (ביטוי); assertNotNull (תוצאה); assertEquals (10, result.getValue ()); }

4. מסקנה

במדריך זה בדקנו מספר אפשרויות שונות לפשט קוד מורכב. למדנו גם כיצד להחליף הצהרות מקוננות על ידי שימוש בדפוסי עיצוב יעילים.

כמו תמיד, אנו יכולים למצוא את קוד המקור השלם במאגר GitHub.


$config[zx-auto] not found$config[zx-overlay] not found