الگوی طراحی دکوراتور چیست؟

48
0
الگوی طراحی دکوراتور

الگوی طراحی دکوراتور را کشف کنید و سلسله‌ مراتب‌های انعطاف‌پذیرتر شی بسازید.

یکی از مهمترین اصول در توسعه نرم افزار، اصل طراحی باز-بسته است. این اصل طراحی تاکید می کند که کلاس ها باید برای گسترش باز باشند، اما برای اصلاح بسته باشند. الگوی طراحی دکوراتور اصل طراحی باز-بسته را در بر می گیرد.

با الگوی طراحی دکوراتور، می‌توانید به راحتی یک کلاس را با رفتار جدید بدون تغییر کد موجود آن، گسترش دهید. الگوی دکوراتور این کار را به صورت پویا در زمان اجرا و با استفاده از ترکیب بندی انجام می دهد. این الگوی طراحی به عنوان جایگزینی انعطاف پذیر برای استفاده از وراثت برای گسترش رفتار شناخته می شود.

الگوی طراحی دکوراتور چگونه کار می کند؟

اگرچه الگوی دکوراتور جایگزینی برای وراثت طبقاتی است، اما برخی از جنبه های وراثت را در طراحی خود گنجانده است. یکی از جنبه های کلیدی الگوی دکوراتور این است که تمام کلاس های آن چه به طور مستقیم یا غیر مستقیم به هم مرتبط هستند.

یک الگوی طراحی دکوراتور معمولی دارای ساختار زیر است:

از نمودار کلاس بالا می بینید که الگوی دکوراتور دارای چهار کلاس اصلی است.

کامپوننت: این یک کلاس (یا رابط) انتزاعی است که به عنوان ابرتایپ برای الگوی دکوراتور عمل می کند.

ConcreteComponent: اینها اشیائی هستند که می توانید در زمان اجرا با رفتارهای مختلف تزئین کنید. آنها از رابط کامپوننت ارث می برند و توابع انتزاعی آن را پیاده سازی می کنند.

دکوراتور: این کلاس انتزاعی است و دارای همان سوپرتایپ شیئی است که تزئین خواهد کرد. در نمودار کلاس، دو رابطه بین کلاس های کامپوننت و دکوراتور مشاهده خواهید کرد. رابطه اول رابطه ارثی است; هر دکوراتور یک جزء است. رابطه دوم مربوط به ترکیب است. هر دکوراتور دارای یک جزء (یا بسته بندی) است.

ConcreteDecorator: اینها دکوراتورهای فردی هستند که به یک جزء رفتار خاصی می دهند. باید توجه داشته باشید که هر دکوراتور بتن دارای یک متغیر نمونه است که به یک جزء اشاره دارد.

پیاده سازی الگوی طراحی دکوراتور در جاوا

یک نمونه برنامه سفارش پیتزا (Pizza) می تواند به اندازه کافی نحوه استفاده از الگوی دکوراتور را برای توسعه برنامه ها نشان دهد. این نرم افزار نمونه پیتزا (Pizza) به مشتریان اجازه می دهد تا پیتزاهایی (Pizza) با چند تاپینگ سفارش دهند. اولین کلاس از الگوی دکوراتور رابط پیتزا (Pizza) است:

public interface Pizza {
    public abstract String description();
    public abstract double cost();
}

رابط پیتزا (Pizza) کلاس جزء است. بنابراین، می توانید یک یا چند کلاس بتن از آن ایجاد کنید. شرکت پیتزا (Pizza) دو نوع اصلی پیتزا (Pizza) را بر اساس خمیر آنها تولید می کند. یک نوع پیتزا دارای خمیر مخمر است:

public class YeastCrustPizza implements Pizza {
    @Override
    public String description() {
        return “Pizza dough made with yeast”;
    }

    @Override
    public double cost() {
        return 18.00;
    }
}

YeastCrustPizza اولین کلاس جاوا بتن از رابط پیتزا است. نوع دیگر پیتزا موجود نان تخت است:

public class FlatbreadCrustPizza implements Pizza {
    @Override
    public String description() {
        return “Pizza dough made with flatbread”;
    }

    @Override
    public double cost() {
        return 15.00;
    }
}

کلاس FlatbreadCrustPizza دومین جزء بتن است و مانند کلاس YeastCrustPizza، تمام توابع انتزاعی رابط پیتزا را پیاده سازی می کند.

دکوراتورها

کلاس دکوراتور همیشه انتزاعی است، بنابراین نمی توانید یک نمونه جدید مستقیماً از آن ایجاد کنید. اما لازم است بین دکوراتورهای مختلف و اجزایی که تزئین خواهند کرد رابطه برقرار کرد.

public abstract class ToppingDecorator implements Pizza {
    public String description() {
        return “Unknown Topping”;
    }
}

کلاس ToppingDecorator نشان دهنده کلاس دکوراتور در این نمونه برنامه است. اکنون شرکت پیتزا می‌تواند با استفاده از کلاس ToppingDecorator، تاپینگ‌ها (یا دکوراتورهای مختلف) ایجاد کند. بیایید فرض کنیم یک پیتزا می تواند سه نوع رویه مختلف داشته باشد، یعنی پنیر، پپرونی و قارچ.

تاپینگ پنیر

public class Cheese extends ToppingDecorator {
    private Pizza pizza;

    public Cheese(Pizza pizza) {
        this.pizza = pizza;
    }

    @Override
    public String description() {
        return pizza.description() + “, Cheese Topping”;
    }

    @Override
    public double cost() {
        return pizza.cost() + 2.50;
    }
}

تاپینگ پپرونی

public class Pepperoni extends ToppingDecorator {
    private Pizza pizza;

    public Pepperoni(Pizza pizza) {
        this.pizza = pizza;
    }

    @Override
    public String description() {
        return pizza.description() + “, Pepperoni Topping”;
    }

    @Override
    public double cost() {
        return pizza.cost() + 3.50;
    }
}

تاپینگ قارچ

public class Mushroom extends ToppingDecorator {
    private Pizza pizza;

    public Mushroom(Pizza pizza) {
        this.pizza = pizza;
    }

    @Override
    public String description() {
        return pizza.description() + “, Mushroom Topping”;
    }

    @Override
    public double cost() {
        return pizza.cost() + 4.50;
    }
}

اکنون یک برنامه کاربردی ساده دارید که با استفاده از الگوی طراحی دکوراتور اجرا شده است. اگر مشتری بخواهد پیتزای مخمری با پنیر و پپرونی سفارش دهد، کد تست برای آن سناریو به صورت زیر خواهد بود:

public class Main {
    public static void main(String[] args) {
        Pizza pizza1 = new YeastCrustPizza();
        pizza1 = new Pepperoni(pizza1);
        pizza1 = new Cheese(pizza1);
        System.out.println(pizza1.description() + ” $” + pizza1.cost());
    }
}

با اجرای این کد خروجی زیر در کنسول تولید می شود:

همانطور که می بینید، خروجی نوع پیتزا را به همراه هزینه کل آن بیان می کند. پیتزا به عنوان یک پیتزا با پوسته مخمر با قیمت 18 دلار شروع شد، اما با الگوی دکوراتور، برنامه توانست ویژگی های جدید و هزینه مناسب آن را به پیتزا اضافه کند. بنابراین، بدون تغییر کد موجود (پیتزا با پوسته مخمر) رفتار جدیدی به پیتزا داد.

با الگوی دکوراتور نیز می توانید هر چند بار که بخواهید همین رفتار را روی یک شی اعمال کنید. اگر مشتری یک پیتزا با همه چیز روی آن و مقداری پنیر اضافی سفارش داد، می‌توانید کلاس اصلی را با کد زیر به‌روزرسانی کنید تا این موضوع را منعکس کند:

Pizza pizza2 = new YeastCrustPizza();
pizza2 = new Pepperoni(pizza2);
pizza2 = new Cheese(pizza2);
pizza2 = new Cheese(pizza2);
pizza2 = new Mushroom(pizza2);

System.out.println(pizza2.description() + ” $” + pizza2.cost());

برنامه به روز شده خروجی زیر را در کنسول تولید می کند:

مزایای استفاده از الگوی طراحی دکوراتور

دو مزیت اصلی استفاده از الگوی طراحی دکوراتور امنیت و انعطاف پذیری است. الگوی دکوراتور به شما امکان می دهد با عدم تداخل با کدهای ایمن از قبل، کد ایمن تری ایجاد کنید. در عوض کد موجود را از طریق ترکیب گسترش می دهد. جلوگیری موثر از معرفی اشکالات جدید یا عوارض جانبی ناخواسته.

با توجه به ترکیب، یک توسعه دهنده همچنین هنگام استفاده از الگوی دکوراتور انعطاف پذیری زیادی دارد. می‌توانید در هر زمان یک دکوراتور جدید برای اضافه کردن رفتار جدید، بدون تغییر کد موجود و ایجاد اختلال در برنامه، پیاده‌سازی کنید.

امتیاز این مطلب
سهیل دهقانی
نوشته شده توسط

سهیل دهقانی

علاقه مند به فناوری و تکنولوژی های روز دنیا کارشناس سئو و تولید محتوا

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

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

گوگل فارکس آموزش تخصصی آمارکتس