1. Ziyaretçi Deseni Nedir
Ziyaretçi deseni, veri yapısını veri işlemlerinden ayıran ve veri yapısını değiştirmeden farklı işlemlerin veri üzerinde gerçekleştirilmesine izin veren davranışsal bir tasarım desenidir. Ziyaretçi deseni, veri yapısını işlemlerden ayırarak işlemleri daha esnek ve genişletilebilir hale getirebilir.
2. Ziyaretçi Deseninin Özellikleri ve Avantajları
Özellikler:
- Veri yapısını işlemlerden ayırarak farklı işlemlerin dinamik olarak bağlanmasını sağlar.
- Yeni işlemler eklemek çok pratiktir ve mevcut kodları değiştirmeyi gerektirmez.
Avantajlar:
- Yeni işlemler eklemek çok pratik olup, açık-kapalı prensibe uygundur.
- Veri yapısı değişmeden karmaşık işlemler gerçekleştirilebilir.
3. Ziyaretçi Deseni Pratik Uygulama Örneği
Ziyaretçi deseninin, derleyici sentaks ağacı analizi aşamasında farklı sentaks kontrollerinin ve kod dönüşüm işlemlerinin uygulanmasında ve veritabanı sorgu optimize edicisinde sorgu ağacı üzerinde çeşitli optimizasyon işlemlerinin gerçekleştirilmesinde geniş bir uygulama alanı bulunmaktadır.
4. Golang'da Ziyaretçi Deseninin Uygulanması
4.1 UML Sınıf Diyagramı
4.2 Örnek Girişi
Ziyaretçi deseni aşağıdaki rolleri içerir:
-
Element
, ziyaretçileri kabul etmek için birAccept
metodunu tanımlar. -
ConcreteElementA
veConcreteElementB
,Accept
metodunu uygulayan ve kendi işlem metodlarını tanımlayan somut element sınıflarıdır. -
Visitor
, belirli elementleri ziyaret etmek için metodları tanımlayan ziyaretçi arayüzüdür. -
ConcreteVisitor1
veConcreteVisitor2
, belirli elementleri ziyaret etmek için metotları uygulayan somut ziyaretçi sınıflarıdır.
4.3 Uygulama Adımı 1: Ziyaretçi Arayüzünü ve Somut Ziyaretçileri Tanımlama
Öncelikle, ziyaretçi arayüzünü ve somut ziyaretçi sınıflarını tanımlamamız gerekiyor:
type Visitor interface {
VisitConcreteElementA(element ConcreteElementA)
VisitConcreteElementB(element ConcreteElementB)
}
type ConcreteVisitor1 struct{}
func (v *ConcreteVisitor1) VisitConcreteElementA(element ConcreteElementA) {
// ConcreteElementA üzerinde işlemler gerçekleştir
}
func (v *ConcreteVisitor1) VisitConcreteElementB(element ConcreteElementB) {
// ConcreteElementB üzerinde işlemler gerçekleştir
}
type ConcreteVisitor2 struct{}
func (v *ConcreteVisitor2) VisitConcreteElementA(element ConcreteElementA) {
// ConcreteElementA üzerinde işlemler gerçekleştir
}
func (v *ConcreteVisitor2) VisitConcreteElementB(element ConcreteElementB) {
// ConcreteElementB üzerinde işlemler gerçekleştir
}
4.4 Uygulama Adımı 2: Element Arayüzünü ve Somut Element Sınıflarını Tanımlama
Sonra, element arayüzünü ve somut element sınıflarını tanımlıyoruz:
type Element interface {
Accept(visitor Visitor)
}
type ConcreteElementA struct{}
func (e *ConcreteElementA) Accept(visitor Visitor) {
visitor.VisitConcreteElementA(e)
}
func (e *ConcreteElementA) OperationA() {
// Belirli element A işlemi için mantık
}
type ConcreteElementB struct{}
func (e *ConcreteElementB) Accept(visitor Visitor) {
visitor.VisitConcreteElementB(e)
}
func (e *ConcreteElementB) OperationB() {
// Belirli element B işlemi için mantık
}
4.5 Uygulama Adımı 3: Obje Yapısını ve Somut Obje Yapısını Tanımlama
Daha sonra, obje yapısını ve somut obje yapısını tanımlıyoruz:
type ObjectStructure struct {
elements []Element
}
func (os *ObjectStructure) Attach(element Element) {
os.elements = append(os.elements, element)
}
func (os *ObjectStructure) Detach(element Element) {
for i, e := range os.elements {
if e == element {
os.elements = append(os.elements[:i], os.elements[i+1:]...)
break
}
}
}
func (os *ObjectStructure) Accept(visitor Visitor) {
for _, element := range os.elements {
element.Accept(visitor)
}
}
4.6 Uygulama Adımı 4: Obje Yapısında Eleman Erişim Arayüzünü Uygulama
Obje yapısında eleman erişim arayüzünü uygulayın ve erişim işlemini ziyaretçiye yetkilendirin:
func (os *ObjectStructure) Accept(visitor Visitor) {
for _, element := range os.elements {
element.Accept(visitor)
}
}
4.7 Uygulama Adımı 5: Ziyaretçi Tasarım Desenini Kullanmak İçin İstemci Kodunu Tanımlayın
Son olarak, ziyaretçi desenini kullanmak için istemci kodunu tanımlarız:
func main() {
elementA := &ConcreteElementA{}
elementB := &ConcreteElementB{}
visitor1 := &ConcreteVisitor1{}
visitor2 := &ConcreteVisitor2{}
objectStructure := &ObjectStructure{}
objectStructure.Attach(elementA)
objectStructure.Attach(elementB)
objectStructure.Accept(visitor1)
objectStructure.Accept(visitor2)
}
Sonuç
Ziyaretçi deseni sayesinde, veri yapısını veri işlemlerinden ayırarak işlemi daha esnek ve genişletilebilir hale getirebiliriz. Golang'da ziyaretçi desenini uygularken, arayüzlerin ve işlevlerin kombinasyonunu kullanarak dinamik bağlama ulaşabiliriz ve bu sayede ayırma işlemi gerçekleşir. Ziyaretçi deseni, sözdizimi ağacı analizi veya veritabanı sorgu optimizasyonu gibi pratik senaryolarda etkili bir şekilde uygulanabilir.