JavaRush /בלוג Java /Random-HE /דפוס Java Decorator

דפוס Java Decorator

פורסם בקבוצה
בספר "ראש ראשון. דפוסי עיצוב" מאת אריק פרימן ואליזבת רובסון מגדירים זאת כך: דפוס הדקורטור מספק באופן דינמי יכולות חדשות לאובייקט ומהווה חלופה לסיווג משנה להרחבת הפונקציונליות. הבה ננסה להסתכל על הגדרה זו ביתר פירוט באמצעות דוגמה. נניח שיצרת עוד דת מודרנית ותתכנן לספק לאנשים את השירותים המתאימים. כי מגמות מודרניות רודף אחר צמחונות, אקולוגיה, התפתחות אנושית, ומשום מה אנשים לא מסתפקים בדתות "מסורתיות" (או אתאיזם בסופו של דבר), ואז אתה, בעקבות הזרם המרכזי, יוצר דת ניו אייג'ית אחרת (מעין סינתזה מהקיים דתות, לוקחות מכל אחת מהן). בהתחלה אתה מספק את השירותים הבאים: 1. חיזוי עתידות 2. הורוסקופ כלומר. הכל נראה כך: יש ממשק שירות עם מחיר כמובן :) ותיאור
public interface Service {
    public double getPrice();
    public String getLabel();
}
ושירותים
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
ובכן, בהתאם, הופיעו 2 פקודות (גילוי עתידות עם קלפי טארוט והורוסקופ אישי מהלקוח):
public static void main(String[] args) {
    double cost;
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    // И персональный гороскоп
    Service personalHoroscope = new Horoscope("Персональный гороскоп", 9000);
    cost = taro.getPrice() + personalHoroscope.getPrice();

    System.out.println(cost);
}
והתוצאה של התוכנית:
10000.0
הכל יהיה בסדר, אבל יש כבר מאות, אם לא אלפים, כמוך, וצריך להמשיך ולפתח את הרוחניות של אנשים, אחרת הם כבר לא מעוניינים. לפיכך, הוצעו אפשרויות נוספות לשירותים הנוכחיים כאופציה. לדוגמה, כאשר בוחרים בשירות חיזוי (טארוט או שאריות קפה), כאפשרות נוספת ניתן להזמין את מאפייני הצ'אקרות או ההילה (בעלות משלהם לכל אחת). כיצד ניתן ליישם זאת כדי לא לבצע שינויים במחלקות השירות הקיימות, בהן הכל כבר מוגדר ומחושב נכון. אתה יכול ליצור כיתות נוספות של חיזוי + צ'אקרות או חיזוי + הילה לגילוי עתידות הנוכחי:
public class Divination implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras implements Service {
    // Здесь своя стоимость и другие методы
}
public class DivinationWithAura implements Service {
    // Здесь своя стоимость и другие методы
}
או פשוט להשתמש בסיווג משנה, כלומר. להרחיב את כיתת ההורים לכיתת הילדים
public class DivinationWithAura extends Divination {
    public DivinationWithAura(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
public class DivinationWithChakras extends Divination {
    public DivinationWithChakras(String label, double price) {
        super(label, price);
    }
    // Здесь своя стоимость и другие методы
}
אבל החסרונות נראים מיד, מפתחים את הרוחניות של העולם כולו, אולי יהיו לנו אפשרויות נוספות חדשות, כלומר כיתות חדשות, ואם עדיין צריך לשלב בין הנוכחיים, אז השיעורים יגדלו במהירות, לפחות אין לנו יותר מספיק משיעור מגיד העתידות עם שתי אפשרויות ביחד, ולא בנפרד:
public class DivinationWithChakrasAndAura implements Service {
    // Здесь своя стоимость и другие методы
}
זה המקום שבו אתה יכול להשתמש בתבנית Decorator מאוד "שומרת" בג'אווה. לשם כך, ניצור מחלקה לאפשרויות נוספות, שתטמיע גם את Service, אך גם תכיל את השירות. ובהתאם לכך, כשנצטרך לבצע הזמנה לגילוי עתידות ואפילו עם 2 אפשרויות ביחד, זה ייראה כך: הממשק כפי שהיה מההתחלה.
public interface Service {
    public double getPrice();
    public String getLabel();
}
2 סוגים של שירותים, כמו קודם:
public class Divination implements Service {
    private String label;
    private double price;

    public Divination(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
public class Horoscope implements Service {
    private String label;
    private double price;

    public Horoscope(String label, double price) {
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price;
    }

    public String getLabel() {
        return this.label;
    }
}
דקורטור לאפשרויות נוספות
public class OptionDecorator implements Service {
    private Service service;
    private String label;
    private double price;

    public OptionDecorator(Service service, String label, double price) {
        this.service = service;
        this.label = label;
        this.price = price;
    }

    public double getPrice() {
        return this.price + service.getPrice();
    }

    public String getLabel() {
        return this.label + service.getLabel();
    }
}
והאפשרויות עצמן (2 עד כה):
public class Aura extends OptionDecorator {
    public Aura(Service service) {
        super(service, "Характеристика ауры", 1500);
    }
}
public class Chakra extends OptionDecorator {
    public Chakra(Service service) {
        super(service, "Характеристика чакр", 500);
    }
}
ובכן, ההזמנה עצמה
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());
}
3000.0
מה שנותן את התוצאה של סכום השירות הראשי ו-2 אפשרויות נוספות. זה אומר שאין צורך בכל תוספת אפשרות (או שילוב של שניהם) ליצירת מחלקה חדשה. בנוסף, ניתן ליישם את האפשרויות הללו לא רק על שירות גילוי עתידות, אלא גם על שירות הורוסקופ. לכן, כאשר בעתיד הקרוב נצטרך ליישם את האפשרויות הנוספות הבאות: - תאימות של שותפי אווטאר ברשתות חברתיות - שיפור תזרים המזומנים באמצעות תקשור מרחוק, נצטרך לכתוב רק 2 מחלקות נוספות:
public class Channeling extends OptionDecorator {
    public Channeling(Service service) {
        super(service, "Полет в Поле Чудес", 99999);
    }
}
public class Avatar extends OptionDecorator {
    public Avatar(Service service) {
        super(service, "Ваша любовь в соц сетях", 5555);
    }
}
ואתה יכול להוסיף אותם לכל שירות:
public static void main(String[] args) {
    // Гадание на Таро
    Service taro = new Divination("Таро", 1000);
    Service chakra = new Chakra(taro);
    Service aura = new Aura(chakra);

    // И общая стоимость
    System.out.println(aura.getPrice());

    // Гороскоп
    Service horoscope = new Horoscope("Персональный гороскоп", 1000);
    Service channenling = new Channeling(horoscope);
    Service avatar = new Avatar(channenling);

    // И общая стоимость
    System.out.println(avatar.getPrice());
}
והתוצאה של התוכנית (שאנו צריכים):
3000.0
106554.0
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION