yusufyilmazfr / tasarim-desenleri-turkce-kaynak

Türkçe kaynağa destek olması amacıyla oluşturulmuş bir kaynaktır. Konu anlatımının yanı sıra C#, Java, Go, Python, Kotlin ve TypeScript gibi birçok dilde tasarım desenlerinin uygulamasını içermektedir.
https://yusufyilmazfr.gitbook.io/tasarim-desenleri-turkce-kaynak/
3.28k stars 454 forks source link

Prototype C# Örneği #39

Open mustafaskilic opened 1 year ago

mustafaskilic commented 1 year ago

Merhaba hocam; Hazırladığınız bu dokümantasyondan oldukça faydalanmaktayım, sunduğunuz bilgi paylaşımı için teşekkür ediyorum. Prototype Design Pattern ile ilgili birkaç araştırma daha yaptım. Ve anladığım kadarıyla verdiğiniz örnek şu an aslında Shallow Copy yapmakta. Employee class' ına property olarak bir class verdiğimizde bu anlaşılmış olacak.

    class Employee : IClonablePrototype<Employee>
    {
    string firstName;
    string lastName;
    public Address Address { get; set; }

    public Employee(string firstName, string lastName, Address address)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.Address = address;
    }

    public Employee Clone()
    {
        return base.MemberwiseClone() as Employee;
    }
    }
    public class Address
    {
    public string Country { get; set; }
    public string City { get; set; }
    }

Program.cs'de şu şekilde

    static void Main(string[] args)
    {
        Employee gulizar = new Employee("Gülizar", "Yılmaz", new Address { Country ="Türkiye", City = "İstanbul"});
        Employee cloneGulizar = gulizar.Clone();

        // Aynı nesne örneklerini farklı referanslarda tutuyor.
        // Birbirinin aynısı ve farklı referanslarda olan nesneler elde ettik.
        Console.WriteLine(gulizar == cloneGulizar);
        Console.WriteLine(gulizar.Address == cloneGulizar.Address);
    }
  1. Console.WriteLine ' de true olarak geleceği görülecektir. Bu da yapılan işlemin Shallow Copy olduğunu göstermektedir.

Şu şekilde modeli revize edersek Deep Copy ' e ulaşırız.

class Employee : IClonablePrototype<Employee>
{
    string firstName;
    string lastName;
    public Address Address { get; set; }

    public Employee(string firstName, string lastName, Address address)
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.Address = address;
    }

    public Employee Clone()
    {
        Employee employee = base.MemberwiseClone() as Employee;
        employee.Address = Address.Clone();
        return employee;
    }
}
public class Address : IClonablePrototype<Address>
{
    public string Country { get; set; }
    public string City { get; set; }

    public Address Clone()
    {
        return base.MemberwiseClone() as Address;
    }
}
yusufyilmazfr commented 1 year ago

Selamlar @mustafaskilic,

Bu issue'u yeni görüyorum, geç oldu gibi kusura bakma lütfen. Güzel düşüncelerin için de çok teşekkür ediyorum.

İç içe referans tipleri olduğunda dediğiniz senaryo olabilir, evet. Döküman boyunca verilen örneklerde primitive veri tipleri olduğu için belki göze çarpmamış olabilir ama iç içe referans tipler olduğunda da dikkat etmek gerekebilir. Burada birkaç çözüm var gibi:

  1. İlk çözüm olarak sizin de dediğiniz gibi nested referans tipler için de bunları gerçekleştirmek (IClonablePrototype<Employee> uygulamak) fakat burada her zaman müdahale edebileceğimiz bir yapı ile de karşılaşamayabiliyoruz. Örneğin kullandığımız 3th party library'e ait bir sınıfa direkt müdahale edemiyoruz.
  2. Bir diğer çözüm ise uygulanan clone metotuna ait implemetasyon'un değiştirilmesi.

Öncesi:

public class Employee implements IClonablePrototype<Employee> {
    String firstName;
    String lastName;

    public Employee(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public Employee clone() throws CloneNotSupportedException {
        return (Employee) super.clone();
    }
}

Sonrası:

public class Employee implements IClonablePrototype<Employee> {
    String firstName;
    String lastName;

    public Employee(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public Employee clone() throws CloneNotSupportedException {
        return new Employee(firstName, lastName);
    }
}

gibi. Bu döküman kapsamında şu anki halinin de bir problemi görünmüyor ama dediğiniz senaryoda problem yaratabilir. Döküman da 2. yönteme göre de düzenlenebilir. Dilerseniz bu kısımları PR göndererek katkıda da bulunabilirsiniz.