تمرین‌های آموزشی

فروشگاه لباس (تا پایان جلسه دوازدهم)

سطح سوال: سخت

آنچه از این جلسه باید بدانید: آشنایی با واسط (Interface)

یک فروشگاه لباس برای نگهداری اطلاعات لباس‌های خود از یک برنامه‌ی جاوا استفاده می‌کند. این فروشگاه چهار نوع لباس (Clothing) دارد که برای هر یک، یک کلاس درنظر گرفته شده است:

  • جوراب (Socks)
  • پیراهن (Shirt)
  • شلوار (Pants)
  • ژاکت (Jacket)

برای هر لباس نیز سه ویژگی مشترک نگهداری می‌شود:

  • نام: name
  • فصل مناسب برای پوشیدن لباس: season (بهار، تابستان، پاییز و زمستان)
  • قیمت پایه: basePrice

یک رفتار مهم و تغییرپذیر در این برنامه، محاسبه‌ی قیمت هر لباس با توجه به تخفیف‌های مختلف (زمستانه، شب یلدا و …) است که هم‌اکنون با این منطق پیاده‌سازی شده‌است:

  • در تخفیف تابستانه: لباس‌های بهاری: 40% تخفیف، لباس‌های تابستانی: 50% تخفیف و لباس‌های زمستانه: 30% تخفیف.
  • در تخفیف زمستانه: لباس‌های پاییزی: 40% تخفیف، لباس‌های زمستانی: 50% تخفیف و لباس‌های تابستانی: 25% تخفیف. به علاوه، تمامی ژاکت‌ها از 10% تخفیف دیگر نیز برخوردار هستند. یعنی یک ژاکت پاییزی ابتدا 40% از قیمتش کسر می‌شود چون لباس پاییزیست و سپس مجددا 10% دیگر نیز از قیمتش کاسته می‌شود.
  • در تخفیف شب یلدا: تمامی ژاکت‌ها: 10% تخفیف، تمامی جوراب‌ها: 20% تخفیف و بقیه‌ی لباس‌ها: 25% تخفیف.

برنامه‌نویس، در نسخه‌ی قدیمی این برنامه در کلاس Clothing یک متد به نامgetPrice با ورودی نوع تخفیف (discountType) قرار داده بود که با توجه به نوع تخفیف، نوع لباس و ویژگی‌های لباس، قیمت نهایی را محاسبه می‌کرد:

public long getPrice(DiscountType discountType) {
    if (discountType == DiscountType.YALDA) {
        // return with YALDA discount
    } else if (discountType == DiscountType.SUMMER) {
        // return with SUMMER discount
    } else if (discountType == DiscountType.WINTER) {
        // return with WINTER discount
    }
    return price;
}

حال پس از چند ماه مسئول فروشگاه از او می‌خواهد چند نوع تخفیف جدید برای مناسبت‌های مختلف اضافه کرده و رفتار چند نوع تخفیف موجود را تغییر دهد. برنامه‌نویس متوجه مساله‌ای می‌شود؛ با اضافه‌کردن این تغییرات به متد getPrice و تغییرات احتمالی آینده، این متد رفته‌رفته بزرگ‌تر و ناخواناتر می‌شود. او با مطالعه‌ی سرفصل‌های چندریختی (Polymorphism) و واسط (Interface) از سایت جاواکاپ به ایده‌ی جدیدی می‌رسد. او برای شروع، متد  getPrice خود را حذف می‌کند؛ ولی او این مباحث را به‌تازگی مطالعه کرده‌است، پس به او کمک کنید تا ایده‌ی خود را پیاده‌سازی کند.

ابتدا بسته‌ی ir.javacup.shop را دانلود کنید.

او می‌خواهد وظیفه‌ی محاسبه‌ی هر تخفیف را به کلاس‌های مجزایی بسپارد. برای این کار ابتدا یک واسط به نام DiscountStrategy ایجاد کنید:

public interface DiscountStrategy {
    long priceByDiscount(Clothing clothing);
}

سپس به ازای هر نوع تخفیف، یک کلاس ایجاد کنید که این واسط را پیاده‌سازی می‌کند. در متدpriceByDiscount هر یک از این کلاس‌ها باید رفتار نوع تخفیف مربوطه را پیاده‌سازی کنید:

  • برای تخفیف تابستانه: کلاس SummerDiscountStrategy
  • برای تخفیف زمستانه: کلاس WinterDiscountStrategy
  • برای تخفیف شب یلدا: کلاس YaldaDiscountStrategy

در کلاس Clothing متد زیر را برای دریافت و ثبت نوع تخفیف فعلی پیاده‌سازی کنید:

public void setDiscountStrategy(DiscountStrategy discountStrategy) {
    // TODO set discountStrategy
}

حال در متد getPrice جدید (که دیگر پارامتر ورودی ندارد) با استفاده از discountStrategy مشخص‌شده، قیمت با تخفیف را محاسبه کرده و برگردانید:

public long getPrice() {
    // TODO get price by considering discountStrategy
}

اگر هیچ discountStrategyای تعیین نشده بود، باید قیمت پایه‌ی لباس برگردانده شود.

مثال:

Jacket linenCoat = new Jacket("Linen Coat", Season.FALL, 100000);
System.out.println("Linen Coat: "  + linenCoat.getPrice());

linenCoat.setDiscountStrategy(new YaldaDiscountStrategy());
System.out.println("Linen Coat with Yalda discount: "  + linenCoat.getPrice());

linenCoat.setDiscountStrategy(new WinterDiscountStrategy());
System.out.println("Linen Coat with Winter discount: "  + linenCoat.getPrice());

Clothing woolenSocks = new Pants("Woolen Socks", Season.WINTER, 10000);
System.out.println("Woolen Socks: "  + woolenSocks.getPrice());

woolenSocks.setDiscountStrategy(new SummerDiscountStrategy());
System.out.println("Woolen Socks with Summer discount: "  + woolenSocks.getPrice());

woolenSocks.setDiscountStrategy(new WinterDiscountStrategy());
System.out.println("Woolen Socks with Winter discount: "  + woolenSocks.getPrice());

خروجی:

Linen Coat: 100000
Linen Coat with Yalda discount: 90000
Linen Coat with Winter discount: 54000
Woolen Socks: 10000
Woolen Socks with Summer discount: 7000
Woolen Socks with Winter discount: 5000

نکته:

متد getPrice از کلاس Clothing نباید از نحوه‌ی محاسبه‌ی تخفیف‌های مختلف خبر داشته باشد. به عبارت دیگر، تمام منطق محاسبه‌ی هر نوع تخفیف باید در کلاس مربوط به خود نوشته شود.

آنچه باید آپلود کنید:

یک فایل زیپ شامل بسته‌ی ir.javacup.shop است. به صورتی که وقتی فایل زیپ را باز می‌کنیم، دقیقا شاخه‌ی ir را ببینیم که درون آن شاخه‌ی javacup و درون آن نیز شاخه‌ی shop قرار دارد. در داخل شاخه‌ی shop پنج فایل با نام‌های Clothing.java و DiscountStrategy.java و SummerDiscountStrategy.java و WinterDiscountStrategy.java و YaldaDiscountStrategy.java باید وجود داشته باشد.

برای داوری تمرین، می‌توانید پاسخ خود را در سایت Quera به نحوی که در بالا گفته شد، بارگذاری کنید.

با ما همراه باشید:

آدرس کانال تلگرام: IranianJavaDevelopers@

آدرس صفحه اینستاگرام: javacup.ir

آدرس گروه لینکدین: Iranian Java Developers

نوشته های مشابه

‫6 دیدگاه ها

  1. سلام . واسه متد setDiscountStrategy با توجه به اینکه discountStrategy یه ورودی از نوع Clothing میگیره نمیدونم چجوری باید پیاده سازیش کنم میشه راهنماییم کنید؟

    1. سلام
      لطفا در کوئرا در بخش «سوال بپرسید» سوالتون رو مطرح کنید. تیم پشتیبانی راهنمایی‌تون می‌کنن.

  2. با سلام و عرض خسته نباشید بسته ir.javacup.shop قابل دانلود نمیباشذ لطفا بررسی کتید …
    با تشکر از سایت خوبتون

    1. سلام
      ما بررسی کردیم و ظاهرا مشکلی وجود نداشت.
      لطفا یکبار دیگر تلاش کنید.
      با تشکر

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا