Yazılım geliştirmede en önemli prensiplerden biri açık-kapalı tasarım prensibidir. Bu tasarım ilkesi, sınıfların genişlemeye açık, ancak değişikliğe kapalı olması gerektiğini vurgular. Dekoratör tasarım deseni, açık-kapalı tasarım ilkesini bünyesinde barındırır.
Dekoratör tasarım modeliyle, bir sınıfı mevcut kodunu değiştirmeden ona yeni davranış vererek kolayca genişletebilirsiniz. Dekoratör deseni bunu çalışma zamanında kompozisyonu kullanarak dinamik olarak yapar. Bu tasarım modeli, davranışı genişletmek için kalıtım kullanmaya esnek bir alternatif olarak bilinir.
Dekoratör Tasarım Kalıbı Nasıl Çalışır?
Dekoratör deseni bir alternatif olsa da sınıf mirası, kalıtımın bazı yönlerini tasarımına dahil eder. Dekoratör modelinin önemli bir yönü, tüm sınıflarının doğrudan veya dolaylı olarak ilişkili olmasıdır.
Tipik bir dekoratör tasarım deseni aşağıdaki yapıya sahiptir:
Yukarıdaki sınıf diyagramından, dekoratör deseninin dört ana sınıfı olduğunu görebilirsiniz.
Bileşen: bu, dekoratör modeli için süper tip olarak hizmet veren soyut bir sınıftır (veya arayüz).
Beton Bileşeni: çalışma zamanında farklı davranışlarla süsleyebileceğiniz nesnelerdir. Bileşen arabiriminden miras alırlar ve onun soyut işlevlerini uygularlar.
Dekoratör: bu sınıf soyuttur ve süsleyeceği nesne ile aynı üst tipe sahiptir. Sınıf diyagramında, bileşen ve dekoratör sınıfları arasında iki ilişki göreceksiniz. İlk ilişki miras ilişkisidir; her dekoratör bir bileşen. İkinci ilişki, kompozisyon ilişkisidir; her dekoratör sahip (veya bir) bileşeni sarar.
BetonDekoratör: bunlar, bir bileşene belirli bir davranış kazandıran bireysel dekoratörlerdir. Her beton dekoratörün, bir bileşene referansı tutan bir örnek değişkeni olduğunu unutmamalısınız.
Dekoratör Tasarım Modelini Java'da Uygulamak
Örnek bir pizza siparişi uygulaması, uygulamaları geliştirmek için dekoratör modelinin nasıl kullanılacağını yeterince gösterebilir. Bu örnek pizza uygulaması, müşterilerin birden fazla soslu pizza sipariş etmesine olanak tanır. Dekoratör deseninin birinci sınıfı, pizza arayüzüdür:
halkarayüzPizza{
halksoyut Sicim Tanım();
halksoyutçiftmaliyet();
}
Pizza arabirimi bileşen sınıfıdır. Böylece ondan bir veya daha fazla somut sınıf oluşturabilirsiniz. Pizza şirketi, hamurlarına göre iki ana pizza türü yapar. Bir tür pizzada mayalı hamur bulunur:
halksınıfMayalı KabukPizzauygularPizza{
@geçersiz kıl
halk Sicim Tanım(){
geri dönmek"Maya ile yapılan pizza hamuru";
}
@geçersiz kıl
halkçiftmaliyet(){
geri dönmek18.00;
}
}
YeastCrustPizza ilk beton Java sınıfı Pizza arayüzünün. Mevcut diğer pizza türü gözlemedir:
halksınıfgözlemekabukPizzauygularPizza{
@geçersiz kıl
halk Sicim Tanım(){
geri dönmek"Gözleme ile yapılan pizza hamuru";
}
@geçersiz kıl
halkçiftmaliyet(){
geri dönmek15.00;
}
}
FlatbreadCrustPizza sınıfı ikinci somut bileşendir ve YeastCrustPizza sınıfı gibi Pizza arabiriminin tüm soyut işlevlerini uygular.
dekoratörler
Dekoratör sınıfı her zaman soyuttur, dolayısıyla doğrudan ondan yeni bir örnek oluşturamazsınız. Ancak farklı dekoratörler ile dekore edecekleri bileşenler arasında bir ilişki kurmak gerekiyor.
halksoyutsınıfToppingDekoratöruygularPizza{
halk Sicim Tanım(){
geri dönmek"Bilinmeyen Tepesi";
}
}
ToppingDecorator sınıfı, bu örnek uygulamadaki dekoratör sınıfını temsil eder. Artık pizza şirketi, ToppingDecorator sınıfını kullanarak birçok farklı sos (veya dekoratör) oluşturabilir. Diyelim ki bir pizzada peynir, sucuk ve mantar olmak üzere üç farklı malzeme olabilir.
peynir sosu
halksınıfPeyniruzanırToppingDekoratör{
özel Pizza pizza;halkPeynir(Pizza pizza){
Bu.pizza = pizza;
}@geçersiz kıl
halk Sicim Tanım(){
geri dönmek pizza.açıklama() + "Peynir Tepesi";
}
@geçersiz kıl
halkçiftmaliyet(){
geri dönmekPizza.maliyet() + 2.50;
}
}
Biberli Tepesi
halksınıfPepperoniuzanırToppingDekoratör{
özel Pizza pizza;halkPepperoni(Pizza pizza){
Bu.pizza = pizza;
}@geçersiz kıl
halk Sicim Tanım(){
geri dönmek pizza.açıklama() + ", Biberli Tepesi";
}
@geçersiz kıl
halkçiftmaliyet(){
geri dönmekPizza.maliyet() + 3.50;
}
}
mantar sos
halksınıfMantaruzanırToppingDekoratör{
özel Pizza pizza;halkMantar(Pizza pizza){
Bu.pizza = pizza;
}
@geçersiz kıl
halk Sicim Tanım(){
geri dönmek pizza.açıklama() + ", Mantar Sosu";
}
@geçersiz kıl
halkçiftmaliyet(){
geri dönmekPizza.maliyet() + 4.50;
}
}
Artık dekoratör tasarım deseni kullanılarak uygulanan basit bir uygulamanız var. Bir müşteri peynir ve biberli mayalı pizza sipariş ederse, bu senaryo için test kodu aşağıdaki gibi görünecektir:
halksınıfAna{
halkstatikgeçersizana(Dize[] bağımsız değişkenler){
pizza pizza1 = yeni YeastCrustPizza();
pizza1 = yeni Biberli (pizza1);
pizza1 = yeni Peynir (pizza1);
System.out.println (pizza1.description() + " $" + pizza1.maliyet());
}
}
Bu kodu çalıştırmak, konsolda aşağıdaki çıktıyı üretecektir:
Gördüğünüz gibi çıktı, toplam maliyetiyle birlikte pizzanın türünü de belirtiyor. Pizza, 18,00 $'a maya hamurlu pizza olarak başladı, ancak dekoratör deseniyle uygulama, pizzaya yeni özellikler ve bunların uygun maliyetini ekleyebildi. Böylece pizzaya mevcut kodu (maya kabuklu pizza) değiştirmeden yeni davranış kazandırmak.
Dekoratör deseni ile aynı davranışı bir nesneye de dilediğiniz kadar uygulayabilirsiniz. Bir müşteri, üzerinde her şey ve biraz ekstra peynir olan bir pizza sipariş ederse, bunu yansıtmak için ana sınıfı aşağıdaki kodla güncelleyebilirsiniz:
pizza pizza2 = yeni YeastCrustPizza();
pizza2 = yeni biberli (pizza2);
pizza2 = yeni Peynir (pizza2);
pizza2 = yeni Peynir (pizza2);
pizza2 = yeni mantar (pizza2);System.out.println (pizza2.description() + " $" + pizza2.maliyet());
Güncellenen uygulama, konsolda aşağıdaki çıktıyı üretecektir:
Dekoratör Tasarım Desenini Kullanmanın Avantajları
Dekoratör tasarım modelini kullanmanın iki büyük avantajı güvenlik ve esnekliktir. Dekoratör deseni, önceden var olan güvenli koda müdahale etmeyerek daha güvenli kod geliştirmenize olanak tanır. Bunun yerine mevcut kodu kompozisyon yoluyla genişletir. Yeni hataların veya istenmeyen yan etkilerin ortaya çıkmasını etkili bir şekilde önleme.
Kompozisyon nedeniyle bir geliştirici, dekoratör modelini kullanırken de çok fazla esnekliğe sahiptir. Mevcut kodu değiştirmeden ve uygulamayı kesintiye uğratmadan yeni davranış eklemek için istediğiniz zaman yeni bir dekoratör uygulayabilirsiniz.