Tags

  • AWS (7)
  • Apigee (3)
  • ArchLinux (5)
  • Array (6)
  • Backtracking (6)
  • BinarySearch (6)
  • C++ (19)
  • CI&CD (3)
  • Calculus (2)
  • DesignPattern (43)
  • DisasterRecovery (1)
  • Docker (8)
  • DynamicProgramming (20)
  • FileSystem (11)
  • Frontend (2)
  • FunctionalProgramming (1)
  • GCP (1)
  • Gentoo (6)
  • Git (15)
  • Golang (1)
  • Graph (10)
  • GraphQL (1)
  • Hardware (1)
  • Hash (1)
  • Kafka (1)
  • LinkedList (13)
  • Linux (27)
  • Lodash (2)
  • MacOS (3)
  • Makefile (1)
  • Map (5)
  • MathHistory (1)
  • MySQL (21)
  • Neovim (10)
  • Network (66)
  • Nginx (6)
  • Node.js (33)
  • OpenGL (6)
  • PriorityQueue (1)
  • ProgrammingLanguage (9)
  • Python (10)
  • RealAnalysis (20)
  • Recursion (3)
  • Redis (1)
  • RegularExpression (1)
  • Ruby (19)
  • SQLite (1)
  • Sentry (3)
  • Set (4)
  • Shell (3)
  • SoftwareEngineering (12)
  • Sorting (2)
  • Stack (4)
  • String (2)
  • SystemDesign (13)
  • Terraform (2)
  • Tree (24)
  • Trie (2)
  • TwoPointers (16)
  • TypeScript (3)
  • Ubuntu (4)
  • Home

    [Creational] Prototype

    Published Apr 29, 2022 [  DesignPattern  ]

    Real world example

    Remember dolly? The sheep that was cloned! Lets not get into the details but the key point here is that it is all about cloning

    In plain words

    Create object based on an existing object through cloning.

    Wikipedia says

    The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects.

    In short, it allows you to create a copy of an existing object and modify it to your needs, instead of going through the trouble of creating an object from scratch and setting it up.

    Example

    /**
     * The example class that has cloning ability. We'll see how the values of field
     * with different types will be cloned.
     */
    class Prototype {
        public primitive: any;
        public component: object;
        public circularReference: ComponentWithBackReference;
    
        public clone(): this {
            const clone = Object.create(this);
    
            clone.component = Object.create(this.component);
    
            // Cloning an object that has a nested object with back reference
            // requires special treatment. After the cloning is completed, the
            // nested object should point to the cloned object, instead of the
            // original object. Spread operator can be handy for this case.
            clone.circularReference = {
                ...this.circularReference,
                prototype: { ...this },
            };
    
            return clone;
        }
    }
    
    class ComponentWithBackReference {
        public prototype;
    
        constructor(prototype: Prototype) {
            this.prototype = prototype;
        }
    }
    
    /**
     * The client code.
     */
    function clientCode() {
        const p1 = new Prototype();
        p1.primitive = 245;
        p1.component = new Date();
        p1.circularReference = new ComponentWithBackReference(p1);
    
        const p2 = p1.clone();
        if (p1.primitive === p2.primitive) {
            console.log('Primitive field values have been carried over to a clone. Yay!');
        } else {
            console.log('Primitive field values have not been copied. Booo!');
        }
        if (p1.component === p2.component) {
            console.log('Simple component has not been cloned. Booo!');
        } else {
            console.log('Simple component has been cloned. Yay!');
        }
    
        if (p1.circularReference === p2.circularReference) {
            console.log('Component with back reference has not been cloned. Booo!');
        } else {
            console.log('Component with back reference has been cloned. Yay!');
        }
    
        if (p1.circularReference.prototype === p2.circularReference.prototype) {
            console.log('Component with back reference is linked to original object. Booo!');
        } else {
            console.log('Component with back reference is linked to the clone. Yay!');
        }
    }
    
    clientCode();
    

    When to use?

    When an object is required that is similar to existing object or when the creation would be expensive as compared to cloning.

    References