1
\$\begingroup\$

As a practice and self-development exercise I have decided to implement design patterns in C#.

I am using polish cuisine as an example in my implementations. In this project I implemented Prototype design pattern.

Model:

public static class PierogiTypes
{
    public const string WithPotatoesAndCheese = "with potatoes and cheese";
    public const string WithGroat = "with groat";
    public const string WithCabbage = "with cabbage";
    public const string WithMeat = "with meat";
    public const string WithStrawberries = "with strawberries";
    public const string WithBlueberries = "with blueberries";
    public const string WithPotatoesAndCheeseButAlsoWithYoghurtAndKetchup = "with potatoes and cheese but also with yoghurt and ketchup";
}

Desgin Pattern:

using Creational.Prototype.Model;

namespace Creational.Prototype.DesignPatters;

public abstract class PierogiPrototype
{
    public Guid Guid { get; }
    public int Count { set; get; }
    public string Type { get; set; }
    
    public PierogiPrototype(int count)
    {
        Guid = Guid.NewGuid();
        Count = count;
    }
    
    public abstract PierogiPrototype Clone();
    public override string ToString()
    {
        return $"Guid: {Guid}, Count: {Count}, Type: {Type}";
    }
}

public class PierogiWithPotatoesAndCheese : PierogiPrototype
{
    public PierogiWithPotatoesAndCheese(int count) : base(count)
    {
        Type = PierogiTypes.WithPotatoesAndCheese;
    }

    public override PierogiPrototype Clone()
    {
        return (PierogiPrototype)MemberwiseClone();
    }
}

.
.
.
.
.

public class PierogiWithBlueberries : PierogiPrototype
{
    public PierogiWithBlueberries(int count) : base(count)
    {
        Type = PierogiTypes.WithBlueberries;
    }

    public override PierogiPrototype Clone()
    {
        return (PierogiPrototype)MemberwiseClone();
    }
}

Program:

class Program
{
    public static void Main()
    {
        var firstPortion = new PierogiWithBlueberries(10);
        Console.WriteLine(firstPortion);
        var secondPortion = firstPortion.Clone();
        Console.WriteLine(secondPortion);
        firstPortion.Count = 5;
        Console.WriteLine(firstPortion);
        Console.WriteLine(secondPortion);
    }
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Problem scope

  • The prototype design pattern is usually used whenever you want to minimize the creation time and/or resources of a complex or costly object
    • Complex: it has several nested data structures (in other words it is a data rich object)
    • Costly: either from time or resource (like CPU or I/O) perspective (like using network/database calls to retrieve initial values)
  • According to my understanding none of the above can be said about your derived classes of the PierogiPrototype

Shallow or Deep copy

  • The MemberwiseClone method performs a shallow copying which means only the top-level properties are copied over
    • In case of a complex object you want to copy all the nested structures as well not just their references
  • I'm unsure that you are aware of the ICloneable interface but it might make sense to take a look at it

Registry or Catalogue

  • The prototype pattern can be extended in a way that there is a central place where you store the prototypes and from where you can create copies
  • In your case you could store all the variants and create a copy by using the Type string
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Thank you for your comment Peter. Its pleasure to meet you again :D. I am making this simple projects as proof of concepts/commemoration exercises. Those might indeed be too simple and exactly fulfill typical use cases. Nevertheless I am more than greateful for your insights. I am fully aware of ICloneable and deep copy/shallow copy mechanisms but in this particular example there is no difference between them. I will keep this one simple and bear in mind the need of deep copy when necessary. Your material to prototype pattern is very interesting, I will make adjustments based on it :D \$\endgroup\$
    – Artur
    Dec 26, 2022 at 21:25
  • 1
    \$\begingroup\$ Hi @Artur, nice to meet you again :). I think it is pretty hard to find a simple, yet repsentative prototype candidate. Like I said this pattern should be used against costly or complex objects. If the data structure does not meet either of the criteria then the pattern feels a bit overkill for that problem. \$\endgroup\$ Dec 27, 2022 at 6:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.