Bu yazıda Bridge Design Pattern‘den ve kullanım şeklinden bahsedeceğiz.
Öncelikle bu tasarım kalıbının ortaya çıkışında etken olan soruna değinelim ve kod örneğimizi de bu sorun üzerinden yapalım.
Diyelim ki biz hem uzaktan kumanda ile yönetilebilen araçlar hem de bunların uzaktan kumandalarını üreten bir projede çalışıyoruz. Örneğin en tepede ortak özelliklerin toplandığı bir Device sınıfımız olsun. Bu Device sınıfından bir TV sınıfı ürettiğimizi düşünelim. Ayrıca bu TV aygınıtını uzaktan yönetmek için de TV sınıfı ile ilişkili bir RemoteTV sınıfına ihtiyacımız olacaktır.
Burası şimdilik tamam.
Daha sonra ürüne Radio için eklemeler yapılması talebi geldi. Biz yine Device sınıfından kalıtarak Radio sınıfını türettik ve yine uzaktan yönetmek için RemoteRadio sınıfını yazdık.
Burası da tamam.
Daha sonra ürüne uzaktan kumandalı araba özelliği eklenmesi talebi geldiğini düşünelim. Ne yapacağız? Yine gidip Device sınıfından ChildCar sınıfını türeteceğiz ve uzaktan yönetmek için de RemoteChildCar sınıfını yazacağız.
Buradaki sıkıntı bu noktada başlıyor. Her gelen yeni talep için böyle yeni sınıflar yazarak, eklemeler yaparak yönetilmesi zor bir koda doğru yönlendiriyoruz projemizi. Kodun çok dallanması geliştirilebilme özelliğini azaltıyor ve SOLID prensiplerinden Open/Closed prensibini uygulayamam yoluna da götürüyor.
Bunun yerine soyut kısımları ve iş yapan kısımları birbirinden ayıracak, bu iki kısım arasında köprü görevi görecek bir interface ile bu işlemi halletmeye çalışacağız. Bu çalışma ile iki tarafın birbirini etkilemeden geliştirme yapılabilmesini hedefliyoruz diğer taraftan.
Şimdi kodlayarak örnekleyelim Bridge Pattern’i.
Device.java
Device interfcace’i bizim TV, Radio gibi uzaktan kumanda edibelin araçlara ait sınıfları implement edeceğiz bir interface. Aynı zamanda köprü görevi görecek olan interface de bu interface.
Radio.java
Radio sınıfımız Device interface’ini implement eden ve onun içerisinden metotların gövdelerini dolduran sınıftır.
TV.java
TV sınıfımız da aynı şekilde Device interface’ini uygulayan ve metotların içini dolduran bir sınıf.
Remote.java
Remote arabirimimiz uzaktan kumanda fonksiyonlarının tanımlandığı birim oluyor bizim için.
BasicRemote.java
BacicRemote sınıfımız Remote arabirimini uyguluyor ve ondan gelen metotların içlerini dolduruyor.
Bu sınıfta dikkat etmemiz gereken 2 nokta var. Birincisi sınıf içerisinde Device tipinde tanımlanmış bir obje mevcut. İkincisi bu sınıfın parametreli yapılandırıcısı Device tipinde bir parametre alıp bu sınıf içerisinde objeye atıyor. Remote arabiriminden gelen metotların içleri doldurulurken de bu device objesi üzerinden çağırım yapılıyor. Örneğin Remote interface’inden gelen power() metodu device objesi üzerinden cihazı açma ya da kapama işlemini gerçekleştiriyor. Bu noktada Device soyutlanmış durumda. Biz onun hangi Device olduğunu bilmiyoruz.Yani aslında araç ve kumanda kısmı birbirinden ayrılmış hale gelmiş oluyorlar. Öte yandan TV için ayrı, Radio için ayrı, kumandalı araba için ayrı sınıflar yazma ihtiyacı yok, tek sınıf ile halledebiliyoruz.
AdvancedRemote.java
AdvancedRemote sınıfımız da BasicRemote sınıfını kalıtıp BasicRemote’dan farklı olarak bir de mute özelliği sunuyor. Yine soyut durumdaki Device’ın setVolume bilgisi kullanılıyor.
MainClass.java
MainClass içerisinde main metodumuz ve Device tipinde parametre kabul eden testDevice metodumuz yer alıyor. main metot içerisinden testDevice metodunu TV ve Radio tipindeki objeler geçirerek çağırıyoruz. testDevice metodu gelen parametre ile bir BasicRemote ve bir de AdvancedRemote nesneleri oluşturuyoruz. BasicRemote objesi üzerinden power ve printStatus metotlarını çağırıyoruz. Akabinde AdvancedRemote nesnesi üzerinden power, mute ve printStatus metotlarını çağırıyoruz. Önce TV sınıfına ait metotların çağırımı, sonrasında da Radio sınıfına ait metotların çağırımı gerçekleştirilecek.
Konsol Çıktısı
Konsol çıktısından görebileceğimiz gibi önce TV sınıfından çağırımlar yapılıyor, ardından da Radio sınıfından çağırımlar yapılıyor.