JavaScript design patterns - Factory Pattern

in #technology6 years ago (edited)

ThumbTemplate - Factory Pattern.png

Factory pattern - part of a series on JavaScript design patterns

Howdy there, folks!

Last time I gave a brief description and some examples of the module pattern, we went over basic concepts like public and private members - and much fun was had by all! If you ain't read it it's at https://steemit.com/technology/@heathenjezzie/javascript-design-patterns-module-pattern -- I will refer back to it from time to time.

You'd think I'd be satisfied...but I never am to be honest

So let's dive into the factory pattern, it will literally make you a more productive programmer! Oh LOL, etc!!!

Why factory?

They say you should never judge a book by its cover, we can judge a design pattern by it's name (sometimes), and the term factory is a descriptive one for sure.

In terms of prevalence the factory pattern might be right up there alongside our old friend module, it's pretty ubiquitous in programming, but I've probably seen it used more in JavaScript than any other language. I recall writing similar functions in c many moons ago, not even knowing at the time that it was a bona-fide pattern. And you will find that often - you'll read up on a particular pattern and realise you've been using it all along...I love that!

So what does the factory pattern actually do for us?

Creating new objects

First I think it's probably best that we swat up and go over the concept of an object. It ain't like c++ or php where an object is an instantiation of a class. Objects are everywhere in JavaScript, strings are objects, numbers are objects, every-bloody-thing is an object. We use their methods all the time without really caring:

    // Methods, methods all over the place
    console.log(Math.floor(Math.random() * 1000000).toString());

In the module pattern article we created a module that returned an object literal -- essentially it's a collection of properties or comma-separated key:value pairs enshrined between a pair of curly braces. The key is the property name we use to reference the property value, example:

    var obj = {
        "property_0": "value 0",
        "property_1": "value 1"
    };

Extremely simple example but makes a point. We can see that the properties are separated by a comma and that the key and value fields of each property are separated by a colon.

So we can use the obj variable to access these properties thusly:

    console.log(obj.property_0);
    console.log(obj.property_1);

I'm not going to spend too much time going in deep on this, just want to make sure we have some idea of what an object literal is. It's worth noting, however, that these values can be anything, a string, a number, an array...another object or even a function! I honestly dunno why some people are so down on JavaScript, I love this:

    var obj = {
        "a_num": 1234,
        "a_string": "'allo M'sieur!",
        "an_array": [
            4321,
            "Quell bitte, Madame!"
            //
            // We could even put another array or object in here
            // if we want...unlimited pah-wah!
        ],
        "an_object": {
            "another_object": {
                "another_array": [
                    "you",
                    "get",
                    "the",
                    "idea!"
                ],
                "even_more_stuff": "some stuff"
            }
        },
        "even_a_function": function() {
            // Imagine we, like, created more objects in here!? Oh
            // my God, just like, you know...my head, can't...like,
            // you know -- literally, etc.
        }
    };

All very nice - these crazy objects can get quite complex, let me tell thee!

You're probably bored with object literals, but there's more. A function can be an object, in fact - the closure functions we saw in the module pattern examples are objects. The module pattern basically returns an object with private and public properties and methods.

    function someObject() {
        // The let keyword is like var only let will
        // ensure the declared value is only available within
        // the scope of the function/object
        //
        // No more tangents...Google it!
        //
        let hide_me = "Private property";
        
        // We can use the mystical this keyword to define
        // public values...yeah, we don't need to be modular
        // and return public properties/methods in an object!
        //
        this.show_me = "Public property";
    }

So how do we use ths? Notice that it isn't a closure, so it is not one of those immediately invoked functions we read about. So it's not a closure, what we really have here is a kind of class (strictly not a class, but why so pedantic?) or maybe a better description is a blueprint. We can use it to create objects which will have their own individual set of properties and methods.

We take that blueprint and we say, hey...JavaScript, gimme a new instance of this blueprint. We can build the same thing a million times if we have the blueprint...so we can make as many of these objects as we like. To do this we need the infamous new keyword:

    // Hey JavaSript! Gimmie a new...umm...someObject?
    //
    var obj = new someObject();
    
    console.log("Why bother? We know it won't work: " + obj.hide_me);
    console.log("Pretty sure this will work: " + obj.show_me);

Now again, I ain't going in all deep on this, just another tangent. We will see more complex examples of this type of thing as we grow older and become wiser.

So what about the factories?

I came up with a rather absurd but hopefully interesting example to help illustrate this admittedly simple concept. Let us imagine that we own an actual factory and it produces people. Actual, living people being churned out by some production line. I'm sure there's like, some maniac out there who would really love to own a business like this, let's imagine we are that despotic individual.

We hire someone to build us our blueprint that we can use to define any type of person. With this blueprint we can produce person after person after person...

    function person() {
        // Let's randomly pick a sex, 0 for male, 1 for female...
        let sex = Math.floor(Math.random() * 2);
        
        let age = 0;
    }
    
    // Jus' churnin' out them people!
    //
    var a_person = new person();
    var another_person = new person();
    
    // Whooooa!
    //
    var twins = [
        new person(),
        new person()
    ];

Mr factory man decides he's fed up with all the babies occupying the shelves of his person shop, so he decides to alter the person() blueprint so that he can create people of any age:

    function person(set_age_to) {
        // Let's randomly pick a sex, 0 for male, 1 for female...
        let sex = Math.floor(Math.random() * 2);
        
        let age = set_age_to;
    }
    
    // Create a 25 year old new-born baby.
    //
    var baby = person(25);

Cool, so every time we create a person from this blueprint we get an individual object with it's own set of properties and even methods. Let's imagine that Mr factory man, high on his own maniacal sense of power, decides that he should be able to change the age of an already living person. He really is nuts, that guy:


    function person(set_age_to) {
        // Let's randomly pick a sex, 0 for male, 1 for female...
        let sex = Math.floor(Math.random() * 2);
        
        let age = set_age_to;
    
        // Let's use this to create some public methods, first
        // the method to the persons name..
        this.setAge = function(set_age_to) {
            age = set_age_to;
        };
        
        // Public member to show age.
        this.getAge = function() {
            return age.toString();
        }
    }

    // Create a 50 year old.
    //
    var new_dude = new person(50);
    
    // Then rob him of 25 years of what short life he has
    // left for a laugh!
    //
    new_dude.setAge(75);
    
    // What age is this "new_dude"?
    //
    console.log(new_dude.getAge());
    // Oh my!

Michael -- you're still going on about objects!

I know. About the factories - we already sort of have one, we have this blueprint and we can churn out people, even set their age.

What we can do next is write another function... a factory function that will produce these nifty little objects for us. The factory pattern is exactly that and you're probably already thinking of ways you can achieve this.

If you're already trying to write one then you're on the right track, the concept itself is expressive enough to tell us most of what we want to know. One of the things people like about churning out the objects in this way is we cut out that pesky new keyword...lot o' folk don't like it simply because they long for more traditional OOP constructs and paradigms like what you'd find in php...I say, go...go use php then! Sa-mattaaaaa-wit-yaaaaa?

Yeah, these factories can be very useful, and may even be seen forming part of a larger pattern. Here is a simple example of a factory that will pump out the people for ol' Mr factory face over there:

    // Our (modified) person() blueprint.
    //
    function person(set_age_to) {
        var age = set_age_to;
        
        // This time we will have a private method so that
        // Mr factory man can have his fun changing peoples
        // ages.
        //
        var setAge = function(set_age_to) {
            age = set_age_to;
        };
            
        
        // We could do the old this thing to declare our
        // private members, but we like this little pattern.
        //
        // By we I mean me...and me.
        //
        return {
            // And reveal a public option that calls the
            // private method directly
            "setAge": setAge,
                
            // Let's have another public method that
            // reveals the age to us
            "getAge": function() {
                return age.toString();
            }
        }
    };
        
        
    // Now here's the factory...
    //
    function newPerson(set_age_to) {
        // The person() object expects the set_age_to
        // parameter.
        //
        // The newPerson() function does not! It can be
        // omitted. If it is, we'll set it to default 0
        if (typeof(set_age_to) === "undefined")
            var set_age_to = 0;
    
        // All good, return the new person!
        return new  person(set_age_to);
    }
    
    // It has never been easier!
    //
    var him = newPerson();
    var her = newPerson(5);
    var they = newPerson(0);
    var zir = newPerson(15);
     var    ze = newPerson(0);
    var etc = newPerson(65536);
    
    // Let's just check it's all working fine..
    //
    console.log("Age of him is " + him.getAge());
    console.log("Age of her is " + her.getAge());
    console.log("Age of they is " + they.getAge());
    console.log("Age of zir is " + zir.getAge());
    console.log("Age of ze is " + ze.getAge());
    console.log("Age of etc is " + etc.getAge());
        

Hopefully you can clearly see the benefits of using a pattern like this -- even with such a simple example. The factory function can make decisions based on parameters given, create, modify and then return the new object for us. And check out the familiar old revealing mechanism, returning the object literal with some public members.

Tasty, eh?

Over-due conclusion:

Factory is fairly simple but absolutely worth knowing, this is a basic example. Best thing to do is go out and tinker, try things. I've gone off on some rather odd tangents in this episode. We explored a few little areas...just enough to whet your whistle as they used to say but hopefully someone is learning something.

If you're new to the factory pattern and you're a bit like me you'll immediately be thinking of all the wonderful things you can do with this pattern. You will see it a lot, and you'll probably use it a lot, too.

Maybe try extending the person() object to store other properties, name, number of legs, arms, heads, etc. Try stuff!

Just don't get all hungry and tripped out on power like old Mr factory man over there, it's bad ju-ju!

Sort:  

Hello! Your post has been resteemed and upvoted by @ilovecoding because we love coding! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On!

Reply !stop to disable the comment. Thanks!

Congratulations @heathenjezzie! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

You received more than 10 upvotes. Your next target is to reach 50 upvotes.

Click here to view your Board of Honor
If you no longer want to receive notifications, reply to this comment with the word STOP

Do not miss the last post from @steemitboard:

Be ready for the next contest!
Trick or Treat - Publish your scariest halloween story and win a new badge

Support SteemitBoard's project! Vote for its witness and get one more award!

Coin Marketplace

STEEM 0.27
TRX 0.11
JST 0.030
BTC 69771.68
ETH 3782.54
USDT 1.00
SBD 3.46