Decorator Design Pattern (Dekoratör Tasarım Kalıbı) Nedir?
Decorator Pattern (Dekoratör Tasarım Kalıbı), bir nesnenin davranışını dinamik olarak değiştirmek için kullanılan yapısal (structural) tasarım desenlerinden biridir. Bu desen, nesne yönelimli programlamada kalıtım (inheritance) yerine kompozisyon (composition) kullanarak işlevselliğin genişletilmesini sağlar.
Ne Zaman Kullanılmalıdır?
Decorator Pattern şu durumlarda kullanışlıdır:
- Mevcut sınıfları değiştirmeden ek işlevler eklemek gerektiğinde.
- Birden fazla davranışın dinamik olarak birleştirilmesi gerektiğinde.
- Kalıtım hiyerarşisini karmaşıklaştırmadan farklı kombinasyonlarla davranış eklemek gerektiğinde.
- Kod tekrarını önleyerek daha esnek bir yapı oluşturmak gerektiğinde.
Decorator Pattern'in Avantajları :
- Mevcut kodu değiştirmeden yeni özellikler eklenebilir.
- Esneklik sağlar, farklı dekoratörler birleştirilebilir.
- Kod tekrarını önler.
Decorator Pattern'in Dezavantajları :
- Çok fazla dekoratör kullanılırsa kod karmaşık hale gelebilir.
- Hata ayıklaması (debugging) zor olabilir.
Decorator Pattern Kullanım Biçimleri
1. Temel Dekoratör Yapısı
interface Coffee {
String getDescription();
double getCost();
}
class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "Sade Kahve";
}
@Override
public double getCost() {
return 5.0;
}
}
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
}
2. Yeni Davranış Ekleyen Dekoratörler
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + ", Süt";
}
@Override
public double getCost() {
return decoratedCoffee.getCost() + 2.0;
}
}
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription() + ", Şeker";
}
@Override
public double getCost() {
return decoratedCoffee.getCost() + 1.0;
}
}
3. Kullanım
public class Main {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " -> Fiyat: " + coffee.getCost() + " TL");
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " -> Fiyat: " + coffee.getCost() + " TL");
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " -> Fiyat: " + coffee.getCost() + " TL");
}
}
Çıktı:
Sade Kahve -> Fiyat: 5.0 TL
Sade Kahve, Süt -> Fiyat: 7.0 TL
Sade Kahve, Süt, Şeker -> Fiyat: 8.0 TL
Gerçek Dünya Senaryosu: Otomobil Özellikleri
interface Car {
String getFeatures();
double getCost();
}
class BasicCar implements Car {
@Override
public String getFeatures() {
return "Standart Araba";
}
@Override
public double getCost() {
return 2000000;
}
}
abstract class CarDecorator implements Car {
protected Car decoratedCar;
public CarDecorator(Car car) {
this.decoratedCar = car;
}
@Override
public String getFeatures() {
return decoratedCar.getFeatures();
}
@Override
public double getCost() {
return decoratedCar.getCost();
}
}
class SunroofDecorator extends CarDecorator {
public SunroofDecorator(Car car) {
super(car);
}
@Override
public String getFeatures() {
return decoratedCar.getFeatures() + ", Sunroof";
}
@Override
public double getCost() {
return decoratedCar.getCost() + 150000;
}
}
class LeatherSeatsDecorator extends CarDecorator {
public LeatherSeatsDecorator(Car car) {
super(car);
}
@Override
public String getFeatures() {
return decoratedCar.getFeatures() + ", Deri Koltuklar";
}
@Override
public double getCost() {
return decoratedCar.getCost() + 300000;
}
}
Kullanım
public class Main {
public static void main(String[] args) {
Car car = new BasicCar();
System.out.println(car.getFeatures() + " -> Fiyat: " + car.getCost() + " TL");
car = new SunroofDecorator(car);
System.out.println(car.getFeatures() + " -> Fiyat: " + car.getCost() + " TL");
car = new LeatherSeatsDecorator(car);
System.out.println(car.getFeatures() + " -> Fiyat: " + car.getCost() + " TL");
}
}
Çıktı:
Standart Araba -> Fiyat: 2000000 TL
Standart Araba, Sunroof -> Fiyat: 2150000 TL
Standart Araba, Sunroof, Deri Koltuklar -> Fiyat: 2450000 TL
Sonuç
Decorator Design Pattern, bir nesnenin davranışını dinamik olarak değiştirmeye olanak tanır. Gerçek dünyada kahve makineleri, otomobil özellikleri, kullanıcı arayüzleri ve veri işleme sistemleri gibi birçok alanda kullanılabilir.