Facade Design Pattern

Facade by itself is pretty simple pattern, and there should be no confusion around it. Basically, in case you want to add some layer of abstraction for the client using your interface, you might want to use Facade.

Let us take a look into a pretty common scenario – customer registration. Customer registration by itself is both common and pretty complex scenario in case you want to get it right. When trying to implement such system, you always have to think about user data validation, getting that data, and then decide how this data is going to be stored. Given different business scenarios, even more parts might come in place. So, it is mostly always the problem when this system is implemented, and someone needs to provide customer registration somewhere else or just might need to reuse an existing logic.

So, Facade in such scenarios might be pretty common. In my own experience, I have used Facade when implementing Licensing System of the software being developed, since License Changes for the current user can be applied from lots of places, and licensing itself contains lots of possible scenarios which must be covered in order to make sure that license is applied for the user that has really bought that license, not some fraud.

Now, I will show you a code sample of how the Facade can be implemented. Your implementation is going to be different probably, and this is completely fine, since your scenario might also be different than this example. Below is the code in C# how Facade can be implemented for simple customer registration:

// This interface is responsible for getting field values (e.g. HTML fields in a web form).
public interface IUserDataReader
{
    string GetFieldValue(string name);
}
 
// This interface is responsible for validating customer data entered
public interface ICustomerDataValidator
{
    bool EmailIsValid(string email);
 
    bool PasswordIsValid(string password);
}
 
// Then, this is the storage point of the new customer
public interface ICustomerRepository
{
    void AddCustomer(string email, string password);
}
 
// There is our Facade interface we are going to give to our clients.
public interface ICustomerRegistrationFacade
{
    bool RegisterNewCustomer();
}
 
/*
And finally, there is our package-private Facade we are not going to share with other clients.
Instead, we might give clients some factory or something else to get the instance of facade interface.
Of course, this example is pretty simplified, but it clearly shows that this is the point where all dependencies are swallowed.
*/
class CustomerRegistrationFacade
    :  ICustomerRegistrationFacade
{
    private readonly ICustomerDataValidator _validator;
    private readonly IUserDataReader _userDataReader;
    private readonly ICustomerRepository _repository;
 
    CustomerRegistrationFacade(ICustomerDataValidator validator, IUserDataReader userDataReader, ICustomerRepository repository)
    {
        _validator = validator;
        _userDataReader = userDataReader;
        _repository = repository;
    }
 
    public bool RegisterNewCustomer()
    {
        var email = _userDataReader.GetFieldValue("email");
        var password = _userDataReader.GetFieldValue("password");
 
        if (!_validator.EmailIsValid(email))
            return false;
 
        if (!_validator.PasswordIsValid(password))
            return false;
 
        _repository.AddCustomer(email, password);
 
        return true;
    }
}

Usage of such Facade can be very simple for the client, since client has no need to think about validation, getting the data, and storing it somewhere else.

if (!facade.RegisterNewCustomer())
    // Return some error.
// Do something else, since new customer is added.

As it can be seen, Facade is a good pattern in case you want to add some layer of abstraction, and restrict sharing of concerns to the client in some package. Instead, your goal is to give functionality to the client that client actually needs instead of making him/her/it worrying about more than it is required.

Finally, you can see more information regarding Facade Design Pattern here (these sources explain it pretty well, too):

  1. https://en.wikipedia.org/wiki/Facade_pattern
  2. https://www.geeksforgeeks.org/facade-design-pattern-introduction/
  3. https://www.tutorialspoint.com/design_pattern/facade_pattern.htm
  4. https://sourcemaking.com/design_patterns/facade

Strategy Design Pattern

Strategy is probably one of the easiest patterns to understand. And even it is pretty simple to provide examples for it, since it can be used almost everywhere you like. So, this article will be short.

First of all, what is the purpose of Strategy? Basically, you use Strategy when you are pretty sure that you are going to need different types of algorithms on the same input. In other words, you provide some abstraction which would operate on the same data, e.g. some list which you might want to sort in ascending order in one scenario, and in descending order in another scenario.

So, let us take a look into the actual example.

// You do not care here about the algorithm. You just know you want the data to get sorted somehow.
interface ISortingAlgorithm
{
    void SortData(List<Data> data);
}
 
// Here, you might want to know some sorting way.
class SortingContext
{
    ISortingAlgorithm GetSortingAlgorithm(int algorithm)
    {
        if (algorithm == 2) return new DescendingSortingAlgorithm();
 
        return new AscendingSortingAlgorithm();
    }
}

Your client would use just SortingContext, and he/she would know nothing of the actual algorithm being used. So, this is it regarding Strategy Design pattern. As I have just told you, it is really simple one.

For more examples if you like, the following sources are pretty good regarding Strategy:

  1. https://en.wikipedia.org/wiki/Strategy_pattern
  2. https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
  3. https://sourcemaking.com/design_patterns/strategy

Memento Design Pattern

This one is pretty simple, so the post is going to be short. Basically, Memento Pattern is used to restore state of an object to a previous one. How is it used? Well, the following posts show that, too:
1. https://www.tutorialspoint.com/design_pattern/memento_pattern.htm
2. https://sourcemaking.com/design_patterns/memento

However, there are some problems with this approach. First of all, examples are not real-world (as always). Secondly, Memento should be revisited from structural point of view. I understand the intent to follow GoG tradition, but maybe the tradition should change a bit? In other words, it is fine to use patterns, but they should be clarified as much as possible. For instance, why there is a name such as CareTaker? It sounds not professional enough. I would suggest to call this like that: MementoList, MementoRepository, etc. In other words, use such names that actually make sense.

So, let us implement Memento in abstract way now. As we can see below, we have three actors – Originator, Memento itself, and MementoRepository (a.k.a. CareTaker for whatever it is).

class Memento<T>
{
    private T _state;
 
    public Memento(T state)
    {
        _state = state;
    }
 
    public T GetState()
    {
        return _state;
    }
}
 
class Originator<T>
{
    private T _state;
 
    public void SetCurrentState(T state)
    {
        _state = state;
    }
 
    public T GetCurrentState()
    {
        return _state;
    }
 
    public Memento<T> GetMemento()
    {
        return new Memento(_state);
    }
 
    public void SetStateFromMemento(Memento<T> memento)
    {
        _state = memento.GetState();
    }
}
 
class MementoRepository<T>
{
    private IList<Memento<T>> _mementos;
 
    public void Add(Memento<T> item)
    {
        _mementos.add(item);
    }
 
    public Memento<T> Get(int index) {
        return _mementos[index];
    }
}

Code sample could be the following:

Originator<String> originator = new Originator<>();
MementoRepository<String> repository = new MementoRepository<>();
 
originator.SetCurrentState("State #1");
originator.SetCurrentState("State #2");
repository.Add(originator.GetMemento());
 
originator.SetCurrentState("State #3");
repository.Add(originator.GetMemento());
 
originator.SetCurrentState("State #4");
originator.SetStateFromMemento(repository.Get(0));

And that is it. Memento Design pattern has been successfully implemented in an abstract way. Now let us take a closer look. In order to have less code, sometimes we can achieve the same functionality through usage of less code. For instance, what if we would use just two actors, i.e. Memento would be skipped? Would it still be a pattern? Actually, it would. See the code that proves this point below:

class Originator<T>
{
    private T _state;
 
    public void SetCurrentState(T state)
    {
        _state = state;
    }
 
    public T GetCurrentState()
    {
        return _state;
    }
}
 
class MementoRepository<T>
{
    private IList<Memento<T>> _mementos;
 
    public void Add(Memento<T> item)
    {
        _mementos.add(item);
    }
 
    public Memento<T> Get(int index)
    {
        return _mementos[index];
    }
}

Now the code sample above would become like this:

Originator<String> originator = new Originator<>();
MementoRepository<String> repository = new MementoRepository<>();
 
originator.SetCurrentState("State #1");
originator.SetCurrentState("State #2");
repository.Add(originator.GetCurrentState());
 
originator.SetCurrentState("State #3");
repository.Add(originator.GetCurrentState());
 
originator.SetCurrentState("State #4");
originator.SetCurrentState(repository.Get(0));

In other words, Memento object itself is not required at all when implementing such a design pattern, since template argument T can be used as Memento itself. In case you would not have generics or templates, Memento object might be needed.

And finally, where this pattern can be used actually? Probably, anywhere where restoration of some data is required. Real-world example could be the following probably: Switching between multiple accounts in the same app. Let us create a semi-toy code for that:

// This can work as Memento just perfectly.
class Account {
    public int Id { get; set; }
    public String Email { get; set; }
    public String SessionKey { get; set; }
}
 
// In real-world scenario, we might want to add the account somewhere.
// This will be the CareTaker
class IAccountManager
{
    void Add(Account item);
 
    Account Get(int id);
}
 
class AccountManager : IAccountManager
{
    private Map<int, Account> _accountsAccessible;
 
    public void Add(Account item) {
        _accountsAccessible[item.Id] = item;
    }
 
    public Account Get(int id) {
        return _accountsAccessible[id];
    }
}
 
// And finally, the Originator can be just some LoginService.
class LoginService
{
    private readonly IAccountManager _manager;
    private Account _account;
 
    public LoginService(IAccountManager manager)
    {
        _manager = manager;
    }
 
    public void Login(String email, String password)
    {
        // Some logging in logic.
        var id = <Some id extraction logic>(email, password);
        var sessionKey = <Some session key extraction logic>(email, password);
 
        _account = new Account(id, email, sessionKey);
 
        // In real-world, we will probably put the correct state as soon as it is retrieved.
        _manager.Add(_account);
    }
 
    public Account GetCurrentAccount()
    {
        return _account;
    }
 
    public void SetCurrentAccount(Account account)
    {
        _account = account;
    }
}

Then, somewhere LoginService can be used for switching between accounts, and for some other reasons that can be thought of.

So, I have shown you how the Memento Design Pattern can be implemented and used in the real-world scenarios.

Iterator Design Pattern

There are some exceptions in the Design Patterns world when design patterns are explained pretty well. Iterator is one of such patterns. However, there is no surprise in that, since this pattern is very easy to use.

So, what is the purpose of this pattern? Basically, this is used when you want to have some custom collection that might have custom way of sequencing your elements. When you have such custom container, then you can use iterator design pattern.

How to implement this pattern? Well, it is very easy. First of all, you provide the implementation for Iterator:

interface Iterator<T> {
    bool HasNext();
 
    T Next();
}

Then, you implement some container that is able to return the iterator of elements specified:

class Container<T> {
    static Iterator<T> GetIterator() {
       return // Iterator<T> is instantiated as a new object
    }
}

And that is it. It is both easy and simple design pattern. I do not think there is something more to tell about it.

When would you use it directly? Probably, never, since all modern languages have interfaces in place that already have Iterator implemented somehow (e.g. C# has IEnumerable). And these interfaces are being implemented in case you actually need custom way of sequencing your elements in the container.

Adapter Design Pattern

This design pattern is pretty easy to use and understand, so this article is going to be short. First of all, why do we need it at all? Well, the main reason is the following – there are some classes that might implement useful algorithms, but we expect a bit different output out of them. For instance:
1) Legacy shape uses top left coordinates, and then height and width for rectangle. We would like to use top left and bottom left coordinates knowing we are talking about rectangle initially.
2) We have old customer authentication interface which expects different type of Customer class that we use.

In other words, there are lots of reasons why Adapter can and should be used. I will give a sketch of real-world example for the customer authentication. Let us say that old authentication API uses the following class for Customer:

public class APICustomer {
    public Email { get; set; }
    public Password { get; set; }
}

And we use the following class:

public class Customer {
    public UserName { get; set; }
    public Password { get; set; }
}

And now we need some adapter that adapts our Customer to APICustomer. We can implement it in the following way:

public class CustomerAdapter {
    public static APICustomer Adapt(Customer c) {
        // Given the circumstances that all users use example.com as email domain.
        // In the Gmail users' database it might actually be so. However, in a more real-world adoption of APICustomer would be much more difficult or even impossible.
        // Still, this is not a bad example to illustrate use of it.
        return new APICustomer { Email = c.UserName + "@example.com", Password = c.Password };
    }
}

And this is it. Basically, I have introduced a pretty simple class that converts object of Customer to APICustomer object. In other words, it means that Adapter does not have any sort of strict obligations regarding use of it, so Adapter might be almost everything that you use everyday in your programming life. Just think about it.

Object Pool Design Pattern

Object Pool Design Pattern is pretty simple one. However, even here tutorials might fail. Let us take a look into a couple of examples:

  1. https://sourcemaking.com/design_patterns/object_pool
  2. https://www.geeksforgeeks.org/object-pool-design-pattern/

Both of these examples talk about performance like it should be the most important thing for the Object Pool while performance here is really important, but it is taken into consideration from a bit different angle. For instance, let us take a look into examples that Object Pool might actually be useful: Parallelization of jobs being performed. This is probably one and only class where Object Pool is actually useful. You take some tasks, you parallelize them across different threads, and you use Object Pool as a Factory or a provider for these objects. Creation and providing of these objects have nothing to do with performance. If you need something to do with performance in the object level, use Prototype for that, not an Object Pool.

In other words, it is correct to say that Object Pool might give some performance benefits. But it is retrieved through the pattern itself instead of through object creation. And finally, we should treat design patterns as an abstract way of designing our algorithms and systems. So, what actually does Object Pool give us? Well, it gives as a pretty centralized and easy to use API to get the objects we might want to get.

Another problem with the Object Pool is the example itself in the first tutorial. Why do we need always to compare design patterns with something which is completely unrelated to the Software Development? So we would be able to pretend that we understand what is this design pattern, yes? Why not trying to ACTUALLY understand and USE it instead of PRETEND? It would be much better for everyone.

So, let us take a look into the following code:

// First, we define the interface for generic Object Pool.
public interface IObjectPool<T>
{
    T Acquire();
 
    void Release(T node);
 
    void SetMaximumPoolSize(int size);
}
 
// Then, we define some Resource. Let us say it will be some node analysing website URL.
public interface IWebsiteURLAnalysisNode
{
    string Analyse(string url);
}
 
// And finally, we have the Object Pool itself:
public class AnalysisNodePool : IObjectPool<IWebsiteURLAnalysisNode>
{
    private static Semaphore _semaphore = new Semaphore(3, 3);
    private static AnalysisNodePool _instance = new AnalysisNodePool();
    private readonly Stack<IWebsiteURLAnalysisNode> _nodes = new Stack<IWebsiteURLAnalysisNode>();
    private readonly IWebsiteURLAnalysisNodeCreator _creator; // This would be initialized somehow, but for simplicity I am not doing this here.
 
    private AnalysisNodePool()
    {
    }
 
    // Would use some IoC Container (like Autofac), but for simplicity this is not bad. Just make sure not to include this into your real projects. Statics are not good if they can be replaced with non-statics.
 
    static AnalysisNodePool GetInstance()
    {
        return _instance;
    }
 
    public IWebsiteURLAnalysisNode Acquire()
    {
        _semaphore.WaitOne();
 
        if (_nodes.Count == 0)
        {
            return _creator.Create();
        }
 
        return _nodes.Pop();
    }
 
    public void Release(IWebsiteURLAnalysisNode node)
    {
        _nodes.Push(node);
 
        _semaphore.Release();
    }
 
    public void SetMaximumPoolSize(int size)
    {
        _semaphore = new Semaphore(size, size);
    }
}

As you can see, example is pretty real, since semaphore is used (to ensure maximum number of resources would get used at the same time). So, this is the example of how to actually use Object Pool design pattern. But why use it for crawler? Well, the reason here is that we know pretty well that number of sockets can be limited. Theoretically, it can be unlimited, but this would give no real benefit, thus adding abstraction to limit number of them in an easy manner is pretty nice way of thinking here. Still, not sure if this is very necessary for simple website crawler projects.

In other words, if you know that you have limited amount of resources that need to be shared among some other classes, then Object Pool Design pattern can be used. The main reason to use Object Pool is to provide some API of acquiring objects representing limited amount of resources, not efficiency as some examples like to say. Efficiency gains might be here, but this is not the reason.

Factory Method Design Pattern

Actually, this is quite simple pattern. However, there are so many inappropriate examples (toy code, non-understandable and useless ones) and even more cryptic explanations that you can easily get confused and think what is the point in using this design pattern? It contains lots of awful examples where using Factory Method does not show its’ possible and practical purpose in no way. For example, let us take a look into a Book Factory! https://sourcemaking.com/design_patterns/factory_method/php/1

Seriously, am I supposed to use this for some Books? Why? What is so special about the book that the book having different title, publisher or any other attribute that can be represented in a primitive data types, i.e. so special that I am supposed to create a Book Factory? Builder for books? Maybe, since there might be massive amount of attributes I would like to set comfortably and abstract setting them. Using Prototype for the Book itself? For the Book itself no way, but if the source is some remote data source, then Prototype can be useful, so Book can really implement ICloneable. But Factory Method for the Book? Maybe there are some ways, but I tend to simplify most difficult processes in most simplistic way possible, so it would be easier to manage them later. Thus, I think Book should not be used as an example for Factory Method. It is just too misleading from actual purpose of this awesome design pattern.

In order to find a proper example for usage of Factory Method, first we should take a couple of points why it is used. Some of the points mentioned in various resources are the following:

  1. Abstraction of new object creation. Yes, this is correct, and it is extremely useful in the IoC Containers where Factory Method is used in this way. However, IoC Containers for this article is a bit too complex example to get real understanding of Factory Method, thus I will leave it out here.
  2. Some say that way how objects are instantiated (created newly in memory or returned from some cache) should not matter for the client. Well, I am not so sure. Even if client will know that new object gets put somewhere and somehow in the memory, I think no client will know exactly the internals of that. If the “new” operator would be really harmful as some people tend to say, then no Object Oriented Programming Language would have operator “new”. As a client, I might want to write code in a way that does not restrict me in any ways. Or at least I would like to have intuitive enough API to write the code. In any case, it is wrong to assume what other developers want from me as an API developer. I can only assume the most standard needs: intuitive and easy to use API, understandable documentation, practical and useful examples (not some too primitive examples like “Hello, World”). However, I really agree that “new” should be avoided if it is possible to get the result without in a more elegant way. But still it should be used somewhere. We just should find proper place for it, not avoid it.
  3. Abstract logic that would come out of direct composition of two actual objects. And this can be quite a real reason to use Factory Method. For instance, you might have some main class for doing something, then you might have another class which also does something where another class has something that does something, and so on. Providing an interface as a proper closure for such type of logic really helps, since it becomes unit testable.
  4. Another thing that is suggested is to use some static class for the main factory. Actually, it is one of the antipatterns that you can think of. If possible, you should avoid this at any costs. What if I intend to use the factory in some model class that creates different objects based on the input provided? With static classes, I would be unable to write unit tests in isolated manner.
  5. And so many more explanations.

There are so many explanations due to the following reasons:

  1. Some people confuse Factory Method with Factory. They are different. Factory is used to create objects whose classes resolve to the same top level definition (parent/grandparent) based on some input parameters. Some even say it is not a pattern, and just a programming technique. Well, we have in this world lots of grammar purifiers. Probably, there is no exception in the developers’ world. So, what actually Factory is? Yes, it is a software development technique. And what a Design Pattern is? Also, it is some sort of software development technique. Thus, simple Factory is also a proper design pattern, since it is a common way to solve the problem specified. Factory is just not the part of GoG patterns. Maybe because it is so obvious and simple that any developer would think about it out of intuition. Still, I think Design Patterns are much more than GoG classics in today’s world.
  2. Some even confuse Factory Method with Abstract Factory. It is a rare case, but I have seen this in code working on the project a couple of years ago.
  3. And most probably just have not enough knowledge in Mathematics, verbal communication is not good enough regarding extremely important things. In other words, they do not actually understand what the Factory Method is, and just pretend to understand. However, they use it all the time. Which is strange, but it happens so.

Thus, I am going to explain this pattern once and for all not to make any confusions regarding it. It is pretty sad to see so many toy examples that are never going to help. So, what example for the Factory Method can be useful? Document factory method INTEGRATED into some document storage medium might be useful example where there is IDocument interface that gives as FileName (e.g. example.json) and its’ JSON representation. For instance, we might have some byte stream and we want to be able to store it in different document storage formats: DOC, DOCX, PDF, HTML, and so on. Currently, we have no idea how to convert that byte[] stream to PDF, DOC, DOCX, and so on. Maybe we do not even know what to expect in that byte[] stream. So, let us create a base class for storage medium based on these unknowns:

// Product participant.
public interface IDocument
{
    string AsJSON { get; }
 
    string FileName { get; }
}
 
// This has not to be a factory or something. It is just a Creator participant, and that is it.
public abstract class DocumentStorageBase
{
    // This is the factory method we are going to use.
    // This is the main point of Factory Method. You can not know exactly what type of document will get created here, but
    // you know that there will be some fixed interface (a.k.a. Product participant).
    protected abstract IDocument Create(byte[] content);
 
    // Just a simple storage method. We have the interface, the data in it, thus we know how to save it in some file.
    public void Store(byte[] content)
    {
        var document = Create(content);
 
        var fileName = document.FileName;
        var json = document.AsJSON;
 
        // Store the document somewhere.
        // Not implementing here, since I want to show the use for pattern, not implementation. You can think of any implementation you like.
    }
}

Then, let us say we know we will have to be able to store PDF documents. So, we introduce two new classes.

// Concrete Product participant.
public class PDFDocument : IDocument
{
    public string AsJSON { get; set; }
 
    public string FileName { get; set; }
}
 
// Concrete Creator Participant.
public class PDFDocumentStorage : DocumentStorageBase
{
    protected override IDocument Create(byte[] content)
    {
        // Some difficult conversion logic that is able to get PDFDocument object from byte[].
        // This class would definitely include some dependency injection.
        return new PDFDocument();
    }
}

And that is it. This is everything about Factory Method. We covered all of the participants, and I have shown a pretty useful example which can really get benefits from the Factory Method. As you can see, Factory Method is extremely powerful pattern, and can be used in such cases where you know just a resulting interface/base class (a.k.a. Product participant), and you want someone else to create Concrete Product participants (i.e. they are created by Concrete Creator participants). And Creator itself is just an abstract class exposing an API method to override Factory Method which is used to create Concrete Product participants.

To sum up everything, Factory Method can be defined in the following way:

  1. It is a Creational Pattern allowing us to defer responsibility of object creation to the child-level through parent-level abstract method definition.
  2. There are four participants: Product (base interface both Client and API developer agree on), Creator (base class which introduced Product creation Factory Method which is abstract and should be implemented by child classes), Concrete Creator (implements the Factory method), Concrete Product (instance of Product interface created by Concrete Creator).
  3. It is useful when you know nothing about concrete products that might be instantiated, but you have a pretty good idea of the interfaces, and you exactly know what needs to be done. In other words, you know WHAT, but you do not know HOW, yet. Or you just want to leave HOW part for later.

Finally, there are some pretty nice explanations regarding Factory Method, too. At least the following one is the single one I was able to find where at least explanation is nice: https://exceptionnotfound.net/the-daily-design-pattern-factory-method/ . Explanation is short, clear, and from this you can really get the idea HOW to use Factory Method. But not sure about WHY. Example is original maybe, but not very useful from the real-world perspective, since it does not show WHY Factory Method should be used. I can code all of the sandwiches without any of the Design Patterns, and I would not lose anything. However, I would lose massive amount of nerves, time, and lots of other stuff if I would try to code smart Website Crawler by trying to include all of the rules in a single class. Or to create God of Documents (a.k.a. God Object that is able to create and store PDF, DOC, DOCX, HTML, XML, and so many more document formats in a single class). By using Factory Method, I can concentrate on the things I know right now, and do not bother that I might not know right now something, since I will always be able to extend the class without violation of SOLID (especially Single Responsibility and Open/Closed principles), and do not worry too much of some unknowns. That is why Factory Method can be used. But for sandwiches, books, colors, shapes… These examples are inappropriate. No one codes different classes for books if title is different. And if one does, then software design in that project should be very messy.

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.