1. Uç Nokta Tasarım Deseni Nedir

1.1 Tanım ve Konsept

Uç Nokta Tasarım Deseni, temel amacı paylaşılan nesnelerin sayısını en aza indirerek belleği tasarruflu kullanmak ve performansı artırmaktır. Uç Nokta Tasarım Deseni, aynı veya benzer nesnelerin paylaşımıyla nesnelerin oluşturulması ve tüketiminin azaltılmasını sağlayarak performans optimizasyonu sağlar.

1.2 Diğer Tasarım Desenlerinden Farkı

Diğer tasarım desenleriyle karşılaştırıldığında, Uç Nokta Tasarım Deseni, temel olarak nesnelerin paylaşımı ve yeniden kullanımına odaklanır. Nesneleri paylaşılabilir iç durumlar ve paylaşılamaz dış durumlar olarak ayırır. İç durumları paylaşarak, nesnelerin oluşturulması ve bellek tüketimi azaltılarak sistemin verimliliği artırılır.

2. Uç Nokta Tasarım Deseninin Özellikleri ve Avantajları

Uç Nokta Tasarım Deseninin temel özellikleri ve avantajları şunlardır:

  • Bellek kullanımının minimize edilmesi: Aynı veya benzer nesnelerin paylaşımıyla bellek tüketimini azaltır.
  • Performansın artırılması: Nesnelerin oluşturulması ve yok edilmesini azaltarak sistem işlemini hızlandırır.
  • Büyük miktarda ince taneli nesneleri destekleme: Bellek alanını çok fazla işgal etmeden büyük miktarda ince taneli nesneler oluşturabilir.
  • Basitleştirilmiş sistem yapısı: Nesnelerin iç ve dış durumlarını ayırarak, sistem yapısını ve karmaşıklığını basitleştirir.

3. Uç Nokta Tasarım Deseninin Pratik Uygulama Örnekleri

Uç Nokta Tasarım Deseni aşağıdaki senaryolarda uygulanabilir:

  • Oyunlardaki parçacık nesneleri: Her parçacık nesnesinin özellikleri iç ve dış durumlar olarak ayrılabilir ve aynı özelliklere sahip parçacık nesneleri paylaşılabilir.
  • Ağ sunucularındaki bağlantı nesneleri: Bağlantı nesnelerinin özellikleri iç ve dış durumlar olarak ayrılabilir ve mevcut bağlantı nesneleri geri dönüştürülmeden önce yeniden kullanılabilir.

4. Golang'da Uç Nokta Tasarım Deseninin Uygulanması

4.1 UML Sınıf Diyagramı

Golang'da Uç Nokta Tasarım Deseninin UML sınıf diyagramı aşağıdaki gibidir:

Golang'da Uç Nokta Tasarım Deseni

4.2 Örnek Tanıtımı

Bu örnekte, Uç Nokta Tasarım Desenine dayalı bir grafik editörü oluşturacağız. Farklı renklerde daireler içerecek ve aynı renkteki daire nesnelerini paylaşarak bellek kullanımını azaltacağız.

4.3 Uygulama Adımları

4.3.1 Uç Nokta Arayüzü ve Somut Uç Nokta Sınıfı Oluşturma

İlk olarak, paylaşılan nesnelerin operasyonlarını tanımlamak için bir Uç Nokta arayüzü oluşturmamız gerekiyor. Daha sonra, SomutUçNokta sınıfını oluşturarak Uç Nokta arayüzünü uygulayabilir ve iç durumları içerebiliriz.

// Uç Nokta, uç nokta nesnelerinin arayüzünü tanımlar
type Uç Nokta interface {
	Operasyon(dışsalDurum string)
}

// SomutUçNokta, Uç Nokta arayüzünü uygulayarak somut uç nokta nesnesini temsil eder
type SomutUçNokta struct {
	içselDurum string
}

// Operasyon, paylaşılan nesnenin operasyon metodunu uygular
func (s *SomutUçNokta) Operasyon(dışsalDurum string) {
	fmt.Printf("Somut uç nokta nesnesi, içsel durum: %s, dışsal durum: %s\n", s.içselDurum, dışsalDurum)
}

4.3.2 Uç Nokta Fabrikası Sınıfı Oluşturma

Daha sonra, uç nokta nesnelerini yönetmek ve paylaşmak için bir Uç Nokta Fabrikası sınıfı oluşturabiliriz. Bu fabrika sınıfı, oluşturulan uç nokta nesnelerini depolamak için bir uçNoktalar sözlüğünü korur.

// UçNoktaFabrikası sınıfı
type UçNoktaFabrikası struct {
	uçNoktalar map[string]UçNokta
}

// GetUçNokta, fabrikadan bir uç nokta nesnesi alır veya oluşturur
func (u *UçNoktaFabrikası) GetUçNokta(anahtar string) UçNokta {
	if un, ok := u.uçNoktalar[anahtar]; ok {
		return un
	}

	uçNokta := &SomutUçNokta{
		içselDurum: anahtar,
	}

	u.uçNoktalar[anahtar] = uçNokta

	return uçNokta
}

4.3.3 İstemci Çağrı Örneği

Son olarak, grafik editörünü uygulamak için uç nokta desenini nasıl kullandığımızı gösteren bir İstemci sınıfı oluşturabiliriz.

// İstemci sınıfı
type İstemci struct {
	uçNokta UçNokta
}

// Operasyon, bir operasyon gerçekleştirir
func (c *İstemci) Operasyon() {
	c.uçNokta.Operasyon("dışsal durum")
}

4.4 Uygulama Düşünceleri ve En İyi Uygulama Uygulamaları

4.4.1 Durum Paylaşımı ve İş Parçacığı Güvenliği

Flyweight desenini kullanırken, iç durumun paylaşımına ve iş parçacığı güvenliğine dikkat edilmelidir. Flyweight nesneleri birden fazla istemci tarafından paylaşıldığı için, iç durumun tutarlılığını sağlamak önemlidir.

4.4.2 Nesne Havuzu Yönetimi

Flyweight nesnelerinin daha iyi yönetilmesi ve yeniden kullanılması için, oluşturulan flyweight nesnelerinin depolanması için nesne havuzları kullanılabilir. Nesne havuzları nesnelerin yeniden kullanımını artırabilir ve nesne oluşturma ve yok etme işlemlerinin üstesinden gelmeye yardımcı olabilir.

4.4.3 Nesne Durumunun Harici Yönetimi

Flyweight deseni, nesnelerin iç durumunu ve harici durumunu ayırır, ancak harici durumun istemci tarafından yönetilmesi gerekir. Flyweight nesneleri kullanılırken, istemcinin harici durumu flyweight nesnesine iletmelidir.

Tam Kod Örneği

Aşağıda tam bir Golang kod örneği bulunmaktadır:

package main

import "fmt"

// Flyweight, bir flyweight nesnesinin arabirimini tanımlar
type Flyweight interface {
    Operation(extrinsicState string)
}

// ConcreteFlyweight, belirli bir flyweight nesnesini temsil eder ve Flyweight arabirimini uygular
type ConcreteFlyweight struct {
    intrinsicState string
}

// Operation, paylaşılan nesneler için işlem yöntemini uygular
func (f *ConcreteFlyweight) Operation(extrinsicState string) {
    fmt.Printf("Somut flyweight nesnesi, iç durum: %s, harici durum: %s\n", f.intrinsicState, extrinsicState)
}

// FlyweightFactory sınıfı
type FlyweightFactory struct {
    flyweights map[string]Flyweight
}

// GetFlyweight, fabrikadan bir flyweight nesnesi alır ya da oluşturur
func (f *FlyweightFactory) GetFlyweight(key string) Flyweight {
    if fw, ok := f.flyweights[key]; ok {
        return fw
    }

    flyweight := &ConcreteFlyweight{
        intrinsicState: key,
    }

    f.flyweights[key] = flyweight

    return flyweight
}

// İstemci sınıfı
type Client struct {
    flyweight Flyweight
}

// Operation, bir işlem gerçekleştirir
func (c *Client) Operation() {
    c.flyweight.Operation("harici durum")
}

func main() {
    factory := &FlyweightFactory{
        flyweights: make(map[string]Flyweight),
    }

    flyweight1 := factory.GetFlyweight("A")
    flyweight1.Operation("harici durum 1")

    flyweight2 := factory.GetFlyweight("B")
    flyweight2.Operation("harici durum 2")

    client := &Client{
        flyweight: factory.GetFlyweight("A"),
    }
    client.Operation()
}