Dekoratör Tasarım Deseni

Dec 27 2022
İstedikten sonra bile kendimi ön plana koyabileceğim Payment adında bir ödeme yöntemi içeren bir arayüzümüz var. Ve yöntemi uygulamak için somut bir DefaultPayment sınıfı, yöntem, ödeme mantığını yapmak için fiyatı bir bağımsız değişken olarak alır.

Kendime öncelik verebilirim, sonra bile istesem

Nescafe fincanınızı hazırladıktan sonra üstüne şeker, hatta üzerine çikolata ekleyebilirsiniz.

Ödeme adında bir ödeme yöntemi içeren bir arayüzümüz var.

Ve yöntemi uygulamak için somut bir DefaultPayment sınıfı , yöntem, ödeme mantığını yapmak için fiyatı bir bağımsız değişken olarak alır.

public interface Payment {
    void pay(BigDecimal price);
}
public class DefaultPayment implements Payment {
    @Override
    public void pay(BigDecimal price) {
        System.out.println("Payed: " + price);
    }
}

public class Client {
    public static void main(String[] args) {
        Payment defaultPayment = new DefaultPayment();
        defaultPayment.pay(BigDecimal.valueOf(100));
    }
}

Diyelim ki ödemek istediğim bir ürünün vergisi var, ne yapabilirim?

Uygulama için değil arayüz için tasarladığımız tasarımımızdan faydalanabiliriz.

Böylece, Payment için bir sınıf oluşturabilir ve onun bir Payment türü olmasına izin verebiliriz ve aynı zamanda Payment'ı özellik olarak tutabiliriz ve yapıcısını kullanarak ödemeyi alabilir ve bu sınıfa TaxPaymentDecorator adını vereceğiz .

public class TaxPaymentDecorator implements Payment {
    private Payment payment;
    private BigDecimal tax = BigDecimal.ZERO;

    public TaxPaymentDecorator(Payment payment) {
        this.payment = payment;
    }

    @Override
    public void pay(BigDecimal price) {
        price = price.add(this.tax);
        payment.pay(price);
    }

    public BigDecimal getTax() {
        return tax;
    }

    public void setTax(BigDecimal tax) {
        this.tax = tax;
    }
}

Ve müşteri, TaxPaymentDecorator'ı şu şekilde kullanabilir:

public class Client {
    public static void main(String[] args) {
        TaxPaymentDecorator taxPaymentDecorator = new TaxPaymentDecorator(new DefaultPayment());
        taxPaymentDecorator.setTax(BigDecimal.valueOf(50));
        taxPaymentDecorator.pay(BigDecimal.valueOf(100));
    }
}

public class DiscountPaymentDecorator implements Payment {
    private Payment payment;
    private BigDecimal discount = BigDecimal.ZERO;

    public DiscountPaymentDecorator(Payment payment) {
        this.payment = payment;
    }

    @Override
    public void pay(BigDecimal price) {
        price = price.subtract(discount);
        payment.pay(price);
    }

    public BigDecimal getDiscount() {
        return discount;
    }

    public void setDiscount(BigDecimal discount) {
        this.discount = discount;
    }
}

public class Client {
    public static void main(String[] args) {
        TaxPaymentDecorator taxPaymentDecorator = new TaxPaymentDecorator(new DefaultPayment());
        taxPaymentDecorator.setTax(BigDecimal.valueOf(50));
        DiscountPaymentDecorator discountPaymentDecorator = new DiscountPaymentDecorator(taxPaymentDecorator);
        discountPaymentDecorator.setDiscount(BigDecimal.valueOf(10));
        discountPaymentDecorator.pay(BigDecimal.valueOf(100));
    }
}

UML diyagramı

Dekoratör tasarım deseni UML diyagramı

Tasarım ilkeleri

Burada üç tasarım ilkesini tartışacağım:

  1. Uygulama için değil bir arayüz için tasarım: Gördüğünüz gibi, Ödeme arayüzünü kullanmak, eski uygulamada herhangi bir değişiklik yapmadan çalışma zamanında dinamik olarak davranış ekleyerek OOP'nin gücünü kullanmamıza yardımcı oldu.
  2. Tasarımınızı genişletmeye açık hale getirin, kapatmaya kapatın: Bu nokta bir öncekiyle ilgili, eski uygulamamız bizi herhangi bir değişiklik yapmaya zorlamadı, ancak eski uygulamayı yeni davranışlar eklemek için genişlettik ve burada onun yerine arayüzü kullanmaktan bahsediyorum. uygulamaya yönelik tasarımdır.
  3. Kalıtım yerine kompozisyonu tercih edin: dekoratör, kalıtımı kullanmaya çalışmak yerine burada kompozisyonu kullanır, genel olarak kalıtımın kullanılması eşleşmeyi artırarak sorunlara neden olabilir ve bunu ayrı bir blogda tartışabiliriz.

Bir nesneye dinamik olarak ek sorumluluklar atayın. Dekoratörler, işlevselliği genişletmek için alt sınıflandırmaya esnek bir alternatif sunar.

Örneğimizde çalışma zamanında dinamik olarak iki sorumluluk ekledik, fiyata vergi ekledik ve fiyattan indirimi çıkardık, DefaultPayment için alt sınıflandırma yapmadık , davranışlarımızı esnek bir şekilde eklemek için OOP'nin gücünü kullandık , ve bu Dekoratör Kalıbı .