Prototype Design Pattern

When learning design patterns, it is really important to see real-world examples to understand actual use for patterns instead of trying to decrypt learning resources and pretend understanding design pattern just because you have read some examples which would never be thought to be used in the real-world. This problem is extremely visible regarding Prototype Design Pattern. Let us look into the examples below:

  1. https://www.tutorialspoint.com/design_pattern/prototype_pattern.htm
  2. https://www.geeksforgeeks.org/prototype-design-pattern/

What could possibly go wrong? Basically, everything with these sources. What are these guys modeling? Some color, some shape? Even the class for different color is created. Have you ever seen someone that creates a class for the color? How many colors are there? Well, modern displays are able to understand at least 16777215 colors or more. So, are you going to create 16777215 or more classes for each color, so you would be able to use prototype? Then, how many shapes are there. Well, there are circle, square, rectangle, triangle. Then, there are lots of 2D irregular shapes. Then, there are extremely massive amount of 3D shapes. Number of colors in the computers can be finite (but this number is still very huge…), but number of shapes is actually infinite.

So, my point is that these two tutorial about Prototype is inappropriate for people who want to learn how to use Prototype in the real-world. They show no real use for the prototype. The one good thing here from these tutorials is that at least Prototype’s goal is correctly defined – create duplicate objects from already existing object in order to save some performance. Yes, this is the correct approach. But do we really need saving performance in order to create some really simple classes? Through prototype, we could even lose performance, since Prototype adds more abstract layer on top of the simple class. Thus, it might even become an asymptotic problem for us if we are going to use just for simple cases like the examples in the examples mentioned.

So, what would be the real-world example where Prototype can actually save the day? Well, all of the calculations, data extractions which are performance-hungry are good candidates for Prototype abstraction. For instance, one of the real-world example can be Website Crawler where there is a class (let’s call it WebsitePage) that contains both URL and HTML Content. In order to get HTML content, it might take quite a long amount of time (up to 1-2 seconds which can be treated as a long amount of time if you need multiple of such classes), since you have to open some remote connection, read some data. After that, you want just to process the page, and be as much as network independent as possible when you already have the HTML page for the URL you want to have. So, here you can use the Prototype. But how?

In order to use Prototype, you first have to implement ICloneable interface (example below is given in C# dialect):

public interface ICloneable<T> {
    T clone();
}

Method clone() will just create the instance of class ICloneable using class’es already existing data. Let us see an example for the WebsitePage class:

public class WebsitePage : ICloneable<WebsitePage> {
 
    public Url { get; set; }
    public HtmlContent { get; set; }
 
    WebsitePage clone() {
        // Note. If you have pretty complex data class here, you can combine Prototype with Builder just right here.
        // But for simplicity, I am not going to do that here.
        return new WebsitePage
        {
            Url = Url,
            HtmlContent = HtmlContent
        };
    }
}

So, where is the performance bottleneck solved? Nowhere. For now at least. Performance bottlenecks are solved in something that most tutorial creators call “Prototype Registry”. However, this naming is really confusing and completely not understandable. Why do we need some registry? We just want to be able to solve the context-related problem and that is why we would like to use the pattern. For Website Crawler case, it would be just a simple Repository being able to create WebsitePage based on URL (this URL can be treated as ID for our so-called “Prototype Registry”). If you like, you can call it like WebsitePagePrototypeRegistry. Just make sure that it is clear enough whose register/repository it is. So, let us implement it:

public class WebsitePageRepository {
    private readonly Dictionary<string, WebsitePage> _pages = new Dictionary<string, WebsitePage>();
 
    public WebsitePage GetPage(string url) {
        // We can even process url and use some finalized form.
        // E.g. we can assume that "http://example.com/page.html" is the same as "http://example.com/page.html#abc".
 
        // In case we have URL already in cache, we just return existing object from cache, and use it.
        if (_pages.ContainsKey(url))
            return _pages[url].Clone();
 
        // This is the actual operation we want to encapsulate, and which can really be slow.
        // Operations such as color creation and other stuff mentioned in examples explaining Prototype are really worthless.
        using (var webClient = new WebClient())
        {
            string htmlCode = webClient.DownloadString(url);
 
            var websitePage = new WebsitePage
            {
                Url = url,
                HtmlContent = htmlCode
            };
 
            _pages[url] = websitePage;
 
            return websitePage;
    }
}
}

And that is it. We have real-world example showing usage of Prototype. As we can see, “Prototype Registry” is the class that is the most important, since it allows us to achieve actual goal we want to achieve. And we really see here real-world use of Prototype to solve real-world problem.

Generally, there are extremely many inappropriate Design Patterns tutorials with trivial and worthless examples that makes extremely confusing to learn Design Patterns. However, my goal is to fill in this gap, and to make sure that people wanting to learn Design Patterns would be able to learn them in a really efficient and non-confusing way through real-world examples.

Leave a Reply

Your email address will not be published. Required fields are marked *