Creational — Oluşturucu Desenler

Prototype

Prototip (Klonlama) Deseni

Amaç: Yeni nesneleri sıfırdan oluşturmak yerine, mevcut bir nesneyi (prototipi) kopyalayarak üretmek.

1

Basit Anlatım

Teknik terim yok — günlük hayattan bir benzetme

Bir dilekçe yazdınız: başlık, adres, tarih, imza alanı, güzel bir yazı tipiyle hazırladınız. Şimdi aynı dilekçeden başka bir kurum için de lazım.

Her şeyi sıfırdan yazmak yerine ne yaparsınız? Fotokopisini çekersiniz ve yalnızca kurum adını değiştirirsiniz. Çok daha hızlıdır.

Doğadan bir örnek

Hücreler bölünerek çoğalır. Yeni hücre, ana hücrenin bir kopyasıdır; doğa her hücreyi sıfırdan tasarlamaz.

Dikkat: Yüzeysel kopya tuzağı

Diyelim ki dilekçenin yanına bir klasör iliştirdiniz. Fotokopi çektiğinizde klasörün kendisi kopyalanmaz, sadece "ekte klasör var" yazısı kopyalanır. İki dilekçe aynı klasörü paylaşıyor olur; birine belge eklerseniz diğerinde de görünür. Gerçek bir kopya için klasörü de ayrıca çoğaltmanız gerekir.

Prototype şunu der: "Elinde hazır bir örnek varsa onu kopyala, sadece farklı olan kısmı değiştir."
2

Teknik Anlamı

Bir yazılımcının bakış açısıyla

Prototype, nesnelerin kendilerini klonlamasını sağlayan bir Clone() metodu tanımlar. İstemci, nesnenin somut sınıfını bilmeden kopyasını üretebilir.

Ne zaman kullanılır?

Shallow copy vs Deep copy

.NET'te Prototype

Avantajlar

Dezavantajlar

3

C# ile Uygulama

Adım adım, çalışan kod örneği

Senaryo: Bir oyunda düşman karakterleri. Her düşmanı sıfırdan yapılandırmak yerine hazır şablonları kopyalıyoruz. Shallow ve deep copy farkını da göstereceğiz.

Adım 1 Prototip arayüzü ve referans tipli bir alan

public interface IPrototype<T>
{
    T ShallowClone();
    T DeepClone();
}

public class Equipment
{
    public List<string> Items { get; set; } = new();
}

Adım 2 Klonlanabilir sınıf

MemberwiseClone() alanları birebir kopyalar. Deep copy için referans tipli Equipment nesnesini de elle kopyalıyoruz.

public class Enemy : IPrototype<Enemy>
{
    public string Name { get; set; } = "";
    public int Health { get; set; }
    public Equipment Gear { get; set; } = new();

    public Enemy ShallowClone() => (Enemy)MemberwiseClone();

    public Enemy DeepClone()
    {
        var copy = (Enemy)MemberwiseClone();
        copy.Gear = new Equipment { Items = new List<string>(Gear.Items) };
        return copy;
    }

    public override string ToString() =>
        $"{Name,-14} Can: {Health,3}  Ekipman: {string.Join(", ", Gear.Items)}";
}

Adım 3 Prototip kayıt defteri (registry)

Hazır şablonları isimle saklayıp istendiğinde kopyasını veren yardımcı sınıf.

public class EnemyRegistry
{
    private readonly Dictionary<string, Enemy> _prototypes = new();

    public void Register(string key, Enemy prototype) => _prototypes[key] = prototype;

    public Enemy Spawn(string key) => _prototypes[key].DeepClone();
}

Adım 4 Kullanım

Tüm parçaları bir araya getiren istemci (client) kodu:

var orcTemplate = new Enemy
{
    Name = "Ork Savaşçı", Health = 120,
    Gear = new Equipment { Items = { "Balta", "Kalkan" } }
};

var registry = new EnemyRegistry();
registry.Register("ork", orcTemplate);

var orc1 = registry.Spawn("ork");
var orc2 = registry.Spawn("ork");
orc2.Name = "Ork Lideri";
orc2.Health = 200;
orc2.Gear.Items.Add("Miğfer");
Console.WriteLine(orc1);
Console.WriteLine(orc2);

Console.WriteLine("\n--- Shallow copy tuzağı ---");
var shallow = orcTemplate.ShallowClone();
shallow.Gear.Items.Add("Zehirli Hançer");
Console.WriteLine($"Şablon : {orcTemplate}");
Console.WriteLine($"Kopya  : {shallow}");
Console.WriteLine($"Aynı ekipman nesnesi mi? {ReferenceEquals(shallow.Gear, orcTemplate.Gear)}");

Konsol çıktısı

Ork Savaşçı    Can: 120  Ekipman: Balta, Kalkan
Ork Lideri     Can: 200  Ekipman: Balta, Kalkan, Miğfer

--- Shallow copy tuzağı ---
Şablon : Ork Savaşçı    Can: 120  Ekipman: Balta, Kalkan, Zehirli Hançer
Kopya  : Ork Savaşçı    Can: 120  Ekipman: Balta, Kalkan, Zehirli Hançer
Aynı ekipman nesnesi mi? True

Kodda dikkat edilmesi gerekenler

Özetle: Prototype, nesneleri kopyalayarak üretir. Pahalı oluşturma maliyetinden kaçınır; ancak referans tipli alanlar için shallow/deep copy ayrımına dikkat edilmelidir.
← Ana sayfaya dön