Yazılım geliştirmede kalıp: Dekoratör kalıbı
Kalıplar, modern yazılım geliştirmede önemli bir soyutlamadır. İyi tanımlanmış terminoloji, açık belgeler sunar ve en iyisinden öğrenirler. Desen serimde öne çıkardığım “Design Patterns: Elements of Reusable Object-Oriented Software” (kısaca Design Patterns) adlı klasik kitap 23 desen içeriyor. Dekoratör deseni, kitaptaki üçüncü doku desenidir. Sorumluluğu olan bir nesneyi dinamik olarak genişletir.
Rainer Grimm, uzun yıllardır yazılım mimarı, ekip lideri ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanır, aynı zamanda sık sık uzmanlık konferanslarında konuşmaktan da keyif alır. Modernes C++ blogunda yoğun bir şekilde C++ tutkusundan bahsediyor.
İlk iki yapısal model adaptör modeli ve köprü modelidir. Dekoratör kalıbı, Python’daki dekoratör deyimiyle karıştırılmamalıdır. İkisinin farklı hedefleri vardır: dekoratör deseni, nesneleri dinamik olarak genişletmenize izin verirken, dekoratör deyimi, işlevleri dinamik olarak genişletmenize izin verir.
İşte dekoratör modeli hakkında gerçekler.
model dekoratör
amaç
Sorumluluğu olan bir nesneyi dinamik olarak genişletir
Ayrıca şöyle bilinir
sarmalayıcılar
kullanım durumu
Component
misal
Aşağıdaki örnek, Dekoratör Kalıbı Wikipedia sayfasındaki örneğe dayanmaktadır.
// decorator.cpp
// (based on https://en.wikipedia.org/wiki/Decorator_pattern)
#include <iostream>
#include <string>
struct Shape {
virtual ~Shape() = default;
virtual std::string GetName() const = 0;
};
struct Circle : Shape {
void Resize(float factor) { radius *= factor; }
std::string GetName() const override {
return std::string("A circle of radius ") +
std::to_string(radius);
}
float radius = 10.0f;
};
struct ColoredShape : Shape {
ColoredShape(const std::string& color, Shape* shape) // (1)
: color(color), shape(shape) {}
std::string GetName() const override {
return shape->GetName() + " which is colored " +
color + "."; // (2)
}
std::string color;
Shape* shape;
};
int main() {
std::cout << 'n';
Circle circle;
ColoredShape colored_shape("red", &circle);
std::cout << colored_shape.GetName() << 'n';
std::cout << 'n';
}
Bu örnekte Shape the Component. Circle anlamına gelir ConcreteComponent Ve ColoredShape için Decorator. ColoredShape artışlar Shape yapıcısında (1), (2)’de üye işlevini çağırın shape->GetName() ve rengiyle süsler.
İşte programın çıktısı:
Eğer biri FramedShape ek bir dekoratör olarak, bunları herhangi bir şekilde birbirine yapıştırabilirsiniz:
// decoratorFrame.cpp
// (based on https://en.wikipedia.org/wiki/Decorator_pattern)
#include <iostream>
#include <string>
struct Shape{
virtual std::string str() const = 0;
};
class Circle : public Shape{
float radius = 10.0f;
public:
std::string str() const override{
return std::string("A circle of radius ") +
std::to_string(radius);
}
};
class ColoredShape : public Shape{
std::string color;
Shape& shape;
public:
ColoredShape(std::string c, Shape& s): color{c}, shape{s} {}
std::string str() const override{
return shape.str() + std::string(" which is coloured ") +
color;
}
};
class FramedShape : public Shape{
Shape& shape;
public:
FramedShape(Shape& s): shape{s} {}
std::string str() const override{
return shape.str() + std::string(" and has a frame");
}
};
int main(){
Circle circle;
ColoredShape coloredShape("red", circle); // (1)
FramedShape framedShape1(circle); // (2)
FramedShape framedShape2(coloredShape); // (3)
std::cout << circle.str() << 'n';
std::cout << coloredShape.str() << 'n';
std::cout << framedShape1.str() << 'n';
std::cout << framedShape2.str() << 'n';
}
the ColoredShape bir tane alır Circle (1), FramedShape a Circle (2) veya bir ColoredShape (3) açık. Karşılık gelen üye işlevleri str farklı kombinasyonları gösterir.
İlgili modeller
faydalar
Bileşik desen, Dekoratör desenine çok benzeyen dokulu bir desendir. Temel fark, ikincisinin yalnızca bir oğlu olmasıdır. Bileşik model, alt öğelerinin sonuçlarını özetlediği için, bir nesneye yeni sorumluluklar da ekler.
(rm)
Haberin Sonu
Yazılım geliştirmede kalıp: Dekoratör kalıbı
Kalıplar, modern yazılım geliştirmede önemli bir soyutlamadır. İyi tanımlanmış terminoloji, açık belgeler sunar ve en iyisinden öğrenirler. Desen serimde öne çıkardığım “Design Patterns: Elements of Reusable Object-Oriented Software” (kısaca Design Patterns) adlı klasik kitap 23 desen içeriyor. Dekoratör deseni, kitaptaki üçüncü doku desenidir. Sorumluluğu olan bir nesneyi dinamik olarak genişletir.

Rainer Grimm, uzun yıllardır yazılım mimarı, ekip lideri ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanır, aynı zamanda sık sık uzmanlık konferanslarında konuşmaktan da keyif alır. Modernes C++ blogunda yoğun bir şekilde C++ tutkusundan bahsediyor.

İlk iki yapısal model adaptör modeli ve köprü modelidir. Dekoratör kalıbı, Python’daki dekoratör deyimiyle karıştırılmamalıdır. İkisinin farklı hedefleri vardır: dekoratör deseni, nesneleri dinamik olarak genişletmenize izin verirken, dekoratör deyimi, işlevleri dinamik olarak genişletmenize izin verir.
İşte dekoratör modeli hakkında gerçekler.
model dekoratör
amaç
Sorumluluğu olan bir nesneyi dinamik olarak genişletir
Ayrıca şöyle bilinir
sarmalayıcılar
kullanım durumu
- Çalışma zamanında tek tek nesnelere yeni sorumluluklar ekleyin veya kaldırın
- Sınıf hiyerarşisini alt sınıflara ayırarak genişletmek (bağdaştırıcı modeline bakın) uygulanamaz

Component
- için ortak arabirimi tanımlar. Decorator ve ConcreteComponent
- Süslenecek nesne
- Temel davranışı tanımlar
- arayüzünü uygula Component
- referansı var Component
- Tüm işlemleri şuraya devret: Component; bu ek olabilir ConcreteDecorator veya bir ConcreteComponent yapı
- davranışını genişletir Component
- Temel bileşeninin üye işlevlerini geçersiz kılar
- Tipik olarak, geçersiz kılma üye işlevinde, temel bileşeninin geçersiz kılma üye işlevini çağırır.
misal
Aşağıdaki örnek, Dekoratör Kalıbı Wikipedia sayfasındaki örneğe dayanmaktadır.
// decorator.cpp
// (based on https://en.wikipedia.org/wiki/Decorator_pattern)
#include <iostream>
#include <string>
struct Shape {
virtual ~Shape() = default;
virtual std::string GetName() const = 0;
};
struct Circle : Shape {
void Resize(float factor) { radius *= factor; }
std::string GetName() const override {
return std::string("A circle of radius ") +
std::to_string(radius);
}
float radius = 10.0f;
};
struct ColoredShape : Shape {
ColoredShape(const std::string& color, Shape* shape) // (1)
: color(color), shape(shape) {}
std::string GetName() const override {
return shape->GetName() + " which is colored " +
color + "."; // (2)
}
std::string color;
Shape* shape;
};
int main() {
std::cout << 'n';
Circle circle;
ColoredShape colored_shape("red", &circle);
std::cout << colored_shape.GetName() << 'n';
std::cout << 'n';
}
Bu örnekte Shape the Component. Circle anlamına gelir ConcreteComponent Ve ColoredShape için Decorator. ColoredShape artışlar Shape yapıcısında (1), (2)’de üye işlevini çağırın shape->GetName() ve rengiyle süsler.
İşte programın çıktısı:

Eğer biri FramedShape ek bir dekoratör olarak, bunları herhangi bir şekilde birbirine yapıştırabilirsiniz:
// decoratorFrame.cpp
// (based on https://en.wikipedia.org/wiki/Decorator_pattern)
#include <iostream>
#include <string>
struct Shape{
virtual std::string str() const = 0;
};
class Circle : public Shape{
float radius = 10.0f;
public:
std::string str() const override{
return std::string("A circle of radius ") +
std::to_string(radius);
}
};
class ColoredShape : public Shape{
std::string color;
Shape& shape;
public:
ColoredShape(std::string c, Shape& s): color{c}, shape{s} {}
std::string str() const override{
return shape.str() + std::string(" which is coloured ") +
color;
}
};
class FramedShape : public Shape{
Shape& shape;
public:
FramedShape(Shape& s): shape{s} {}
std::string str() const override{
return shape.str() + std::string(" and has a frame");
}
};
int main(){
Circle circle;
ColoredShape coloredShape("red", circle); // (1)
FramedShape framedShape1(circle); // (2)
FramedShape framedShape2(coloredShape); // (3)
std::cout << circle.str() << 'n';
std::cout << coloredShape.str() << 'n';
std::cout << framedShape1.str() << 'n';
std::cout << framedShape2.str() << 'n';
}
the ColoredShape bir tane alır Circle (1), FramedShape a Circle (2) veya bir ColoredShape (3) açık. Karşılık gelen üye işlevleri str farklı kombinasyonları gösterir.

İlgili modeller
- Bileşik desen, Dekoratör’e benzer dokulu bir desendir. Temel fark, Dekoratör modelinin yalnızca bir çocuğu olmasıdır. Bileşik model, alt öğelerinin sonuçlarını özetlediği için, bir nesneye yeni sorumluluklar da ekler.
- Bağdaştırıcı modeli, bir nesnenin arayüzünü değiştirirken, dekoratör nesnenin sorumluluklarını genişletir.
- Bridge modelinin amacı, arabirimi uygulamadan ayırmaktır. Dekoratörler takılabilir, ancak jumper veya adaptör yoktur.
- Strateji modeli, uygulamayı değiştirmek için nesneleri kullanır, ancak dekoratör, nesnenin sorumluluklarını genişletmek için nesneleri kullanır.
faydalar
- Dekoratörler, çalışma zamanında üst üste yerleştirilebilir.
- Her dekoratör, davranışın bir varyantını uygulayabilir ve bu nedenle tek sorumluluk ilkesini izler.
- Üye işlevlere atanan çağrılar nedeniyle, kontrol akışını takip etmek zordur.
- Temsilci atanan üye işlevlerin çağrılması program performansını etkileyebilir.
- Bir dekoratörü birbirine yapıştırılmış dekoratörlerden çıkarmak oldukça zordur.
Bileşik desen, Dekoratör desenine çok benzeyen dokulu bir desendir. Temel fark, ikincisinin yalnızca bir oğlu olmasıdır. Bileşik model, alt öğelerinin sonuçlarını özetlediği için, bir nesneye yeni sorumluluklar da ekler.
(rm)
Haberin Sonu