Dekoratör Tasarım Deseni: Yazılımın Süsleyicileri
[en] Read in English 2023-06-15
Bir zamanlar, bir “Component” adında bir nesne varmış. Bu nesne, belirli bir işlevi yerine getirmek için kullanılırmış. Ancak, bazen bu işlevi genişletmek veya değiştirmek gerekiyormuş. İşte bu noktada “Decorator"lar devreye giriyormuş.
Decorator’lar, Component’i “süsleyen” veya genişleten nesnelerdir. Bir Decorator, bir Component’in üzerine gelir ve onun işlevini genişletir veya değiştirir. Bu, Component’in kendisini değiştirmeden, onun işlevselliğini genişletmek için kullanılır.
Örneğin, bir “TextComponent” düşünün. Bu component, bir metni ekrana yazdırır. Ancak, bazen metni kalın veya italik yapmak isteyebiliriz. İşte bu noktada “BoldDecorator” veya “ItalicDecorator” devreye girer. Bu decorator’lar, TextComponent’in üzerine gelir ve metni kalın veya italik yaparlar.
Decorator pattern, bu şekilde çalışır. Bir component ve onu genişleten bir dizi decorator ile, çok çeşitli işlevleri gerçekleştirebiliriz.
İşte decorator pattern’ın bir sınıf diyagramı:
Bu diyagramda, bir “Component” ve bu component’i süsleyen veya genişleten bir dizi “Decorator” görebilirsiniz. “ConcreteComponent” sınıfı, “Component” sınıfını genişletir ve belirli bir işlevi yerine getirir. “Decorator” sınıfı da “Component” sınıfını genişletir ve bir “Component” nesnesini içerir. “ConcreteDecoratorA” ve “ConcreteDecoratorB” sınıfları, “Decorator” sınıfını genişletir ve belirli bir işlevi yerine getirir.
Öncelikle, C# dilinde bir örnek vereceğim:
// Component
public abstract class Component
{
public abstract void Operation();
}
// ConcreteComponent
public class ConcreteComponent : Component
{
public override void Operation()
{
// ...
}
}
// Decorator
public abstract class Decorator : Component
{
protected Component component;
public Decorator(Component component)
{
this.component = component;
}
public override void Operation()
{
if (component != null)
{
component.Operation();
}
}
}
// ConcreteDecoratorA
public class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(Component component) : base(component) { }
public override void Operation()
{
base.Operation();
// Additional behavior
}
}
// ConcreteDecoratorB
public class ConcreteDecoratorB : Decorator
{
public ConcreteDecoratorB(Component component) : base(component) { }
public override void Operation()
{
base.Operation();
// Additional behavior
}
}
Bu kodda, bir “Component” ve bu component’i süsleyen veya genişleten bir dizi “Decorator” oluşturduk. “ConcreteComponent” sınıfı, “Component” sınıfını genişletir ve belirli bir işlevi yerine getirir. “Decorator” sınıfı da “Component” sınıfını genişletir ve bir “Component” nesnesini içerir. “ConcreteDecoratorA” ve “ConcreteDecoratorB” sınıfları, “Decorator” sınıfını genişletir ve belirli bir işlevi yerine getirir.
Java:
// Component
public interface Component {
void operation();
}
// ConcreteComponent
public class ConcreteComponent implements Component {
public void operation() {
// ...
}
}
// Decorator
public abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
if (component != null) {
component.operation();
}
}
}
// ConcreteDecoratorA
public class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
public void operation() {
super.operation();
// Additional behavior
}
}
// ConcreteDecoratorB
public class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
public void operation() {
super.operation();
// Additional behavior
}
}
Go:
// Component
type Component interface {
Operation() string
}
// ConcreteComponent
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() string {
return "ConcreteComponent"
}
// Decorator
type Decorator struct {
component Component
}
func (d *Decorator) Operation() string {
if d.component != null {
return d.component.Operation()
}
return ""
}
// ConcreteDecoratorA
type ConcreteDecoratorA struct {
Decorator
}
func (c *ConcreteDecoratorA) Operation() string {
return "ConcreteDecoratorA(" + c.Decorator.Operation() + ")"
}
// ConcreteDecoratorB
type ConcreteDecoratorB struct {
Decorator
}
func (c *ConcreteDecoratorB) Operation() string {
return "ConcreteDecoratorB(" + c.Decorator.Operation() + ")"
}
Rust:
// Component
trait Component {
fn operation(&self) -> String;
}
// ConcreteComponent
struct ConcreteComponent;
impl Component for ConcreteComponent {
fn operation(&self) -> String {
String::from("ConcreteComponent")
}
}
// Decorator
struct Decorator<T: Component> {
component: T,
}
impl<T: Component> Component for Decorator<T> {
fn operation(&self) -> String {
self.component.operation()
}
}
// ConcreteDecoratorA
struct ConcreteDecoratorA<T: Component> {
decorator: Decorator<T>,
}
impl<T: Component> Component for ConcreteDecoratorA<T> {
fn operation(&self) -> String {
let base_operation = self.decorator.operation();
format!("ConcreteDecoratorA({})", base_operation)
}
}
// ConcreteDecoratorB
struct ConcreteDecoratorB<T: Component> {
decorator: Decorator<T>,
}
impl<T: Component> Component for ConcreteDecoratorB<T> {
fn operation(&self) -> String {
let base_operation = self.decorator.operation();
format!("ConcreteDecoratorB({})", base_operation)
}
}
Bu örnekler, decorator pattern’ın farklı dillerde nasıl uygulanabileceğini gösterir. Her dilin kendi özelliklerine ve sözdizimine sahip olduğunu unutmayın, bu yüzden her dil için örnekler biraz farklı olabilir.