Singleton nesne kullanımını zaten inceledik, ancak bu stratejinin bir tasarım modeli olduğunu ve bu konuda en çok kullanılanlardan biri olduğunu henüz fark etmemiş olabilirsiniz.
Aslında, bu kalıplardan pek çok var ve bunlar özel amaçlarına göre sınıflandırılabilirler.
Desen sınıflandırması
Desen Tipi | Başvuru |
---|---|
yaratıcı | Nesne oluşturma problemini çözen bir tür |
Yapısal | Mimarimizde doğru ve genişletilebilir bir sınıf hiyerarşisi oluşturmamızı sağlayan kalıplar |
Davranışsal | Bu kalıp kümesi, bir programdaki nesneler arasında güvenli ve uygun etkileşimi kolaylaştırır. |
Tipik olarak, bir model çözdüğü problemle karakterize edilir. Java ile çalışırken en sık karşılaştığımız birkaç kalıba bir göz atalım:
Model | Amaç |
---|---|
Tekil | Bu kalıba zaten aşinayız - birden fazla örneğe sahip olamayacak bir sınıf oluşturmak ve bu sınıfa erişmek için kullanıyoruz. |
Yineleyici | Biz de buna aşinayız. Bu kalıbın, bir koleksiyon nesnesinin iç temsilini açığa çıkarmadan yinelememize izin verdiğini biliyoruz. Koleksiyonlarla birlikte kullanılır. |
Adaptör | Bu kalıp, uyumsuz nesneleri birlikte çalışabilmeleri için birbirine bağlar. Bağdaştırıcı modelinin adının, bunun tam olarak ne yaptığını hayal etmenize yardımcı olduğunu düşünüyorum. İşte gerçek hayattan basit bir örnek: duvar prizi için bir USB adaptörü. |
Şablon yöntemi |
Entegrasyon problemini çözen ve bir algoritmanın yapısını değiştirmeden algoritmik adımları değiştirmenize izin veren bir davranışsal programlama modeli. Bir dizi montaj adımı şeklinde bir araba montaj algoritmasına sahip olduğumuzu hayal edin: Şasi -> Gövde -> Motor -> Kabin İçi Güçlendirilmiş bir çerçeve, daha güçlü bir motor veya ek aydınlatmalı bir iç mekan koyarsak, algoritmayı değiştirmemiz gerekmez ve soyut sıralama aynı kalır. |
Dekoratör | Bu model, nesnelere yararlı işlevsellik kazandırmak için sarmalayıcılar oluşturur. Bunu bu makalenin bir parçası olarak ele alacağız. |
Java.io'da aşağıdaki sınıflar kalıpları uygular:
Model | Java.io'da nerede kullanılır? |
---|---|
Adaptör |
|
Şablon yöntemi | |
Dekoratör |
dekoratör deseni
Bir ev tasarımı için bir model tarif ettiğimizi düşünelim.
Genel olarak, yaklaşım şöyle görünür:
Başlangıçta, birkaç ev tipi seçeneğimiz var. Minimum konfigürasyon, çatılı bir kattır. Ardından, evin fiyatını doğal olarak etkileyen ek parametreleri değiştirmek için her türlü dekoratörü kullanıyoruz.
Soyut bir House sınıfı yaratıyoruz:
public abstract class House {
String info;
public String getInfo() {
return info;
}
public abstract int getPrice();
}
Burada 2 yöntemimiz var:
- getInfo() evimizin adı ve özellikleri hakkında bilgi verir;
- getPrice(), geçerli ev yapılandırmasının fiyatını döndürür.
Ayrıca standart Ev uygulamalarımız da var — tuğla ve ahşap:
public class BrickHouse extends House {
public BrickHouse() {
info = "Brick House";
}
@Override
public int getPrice() {
return 20_000;
}
}
public class WoodenHouse extends House {
public WoodenHouse() {
info = "Wooden House";
}
@Override
public int getPrice() {
return 25_000;
}
}
Her iki sınıf da Ev sınıfını devralır ve fiyat yöntemini geçersiz kılarak standart bir ev için özel bir fiyat belirler. Yapıcıda adı belirledik.
Ardından, dekoratör sınıfları yazmamız gerekiyor. Bu sınıflar aynı zamanda House sınıfını da devralır . Bunu yapmak için soyut bir dekoratör sınıfı oluşturuyoruz.
Bir nesneyi değiştirmek için ek mantık koyacağımız yer burasıdır. Başlangıçta ek bir mantık olmayacak ve soyut sınıf boş olacaktır.
abstract class HouseDecorator extends House {
}
Daha sonra dekoratör uygulamalarını oluşturuyoruz. Eve ek özellikler eklememize izin veren birkaç sınıf oluşturacağız:
public class SecondFloor extends HouseDecorator {
House house;
public SecondFloor(House house) {
this.house = house;
}
@Override
public int getPrice() {
return house.getPrice() + 20_000;
}
@Override
public String getInfo() {
return house.getInfo() + " + second floor";
}
}
Evimize ikinci bir kat ekleyen bir dekoratör |
Dekoratör yapıcı, "süsleyeceğimiz", yani değişiklikler ekleyeceğimiz bir evi kabul eder. Ve getPrice() ve getInfo() yöntemlerini geçersiz kılarak , eski evi temel alarak güncellenen yeni ev hakkında bilgi döndürürüz.
public class Garage extends HouseDecorator {
House house;
public Garage(House house) {
this.house = house;
}
@Override
public int getPrice() {
return house.getPrice() + 5_000;
}
@Override
public String getInfo() {
return house.getInfo() + " + garage";
}
}
Evimize bir garaj ekleyen bir dekoratör |
Artık evimizi dekoratörlerle güncelleyebiliriz. Bunu yapmak için bir ev yaratmamız gerekiyor:
House brickHouse = new BrickHouse();
Ardından,evevimize geçen yeni bir dekoratöre eşit değişken:
brickHouse = new SecondFloor(brickHouse);
Bizimevdeğişken şimdi ikinci katı olan bir ev.
Dekoratörleri içeren kullanım durumlarına bakalım:
Örnek kod | Çıktı |
---|---|
|
Tuğla ev 20000 |
|
Tuğla Ev + ikinci kat 40000 |
|
Tuğla Ev + ikinci kat + garaj 45000 |
|
Ahşap Ev + garaj + ikinci kat 50000 |
|
Ahşap ev 25000 Ahşap Ev + garaj 30000 |
Bu örnek, bir nesneyi bir dekoratörle yükseltmenin faydasını göstermektedir. Yani değiştirmedikAhşap evnesnenin kendisi, ancak bunun yerine eskisini temel alan yeni bir nesne yarattı. Burada avantajların dezavantajlarla birlikte geldiğini görebiliriz: her seferinde bellekte yeni bir nesne yaratarak bellek tüketimini artırırız.
Programımızın şu UML diyagramına bakın:

Bir dekoratörün süper basit bir uygulaması vardır ve nesneleri dinamik olarak değiştirerek onları yükseltir. Dekoratörler, geçerli sınıfla aynı soyut türdeki veya arabirimdeki nesneleri parametre olarak alan yapıcıları tarafından tanınabilir. Java'da bu kalıp, G/Ç sınıflarında yaygın olarak kullanılır.
Örneğin, daha önce belirttiğimiz gibi, java.io.InputStream , OutputStream , Reader ve Writer'ın tüm alt sınıfları , aynı sınıfların nesnelerini kabul eden bir kurucuya sahiptir.
GO TO FULL VERSION