Challenge: Solution Review
This lesson will explain the solution to the problem from the last coding challenge.
We'll cover the following
Solution #
function Assignment() {this.make = function(builder){builder.step1();builder.step2();builder.step3();builder.step4();return builder.get();}}function AssignmentBuilder(subject,level,dueDate) {this.assignment = null;this.step1 = function() {this.assignment= new Task();};this.step2 = function() {this.assignment.addSubject(subject);};this.step3 = function(){this.assignment.addLevel(level);}this.step4 = function(){this.assignment.addDuedate(dueDate);}this.get = function() {return this.assignment;};}function Task() {this.subject = null;this.level = null;this.dueDate = null;this.addSubject = function(subject) {this.subject = subject;};this.addLevel = function(level) {this.level = level;};this.addDuedate = function(dueDate){this.dueDate = dueDate;}this.announcement = function(){console.log(`Your ${this.subject} assigment is ${this.level} and due on ${this.dueDate}.`)}}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
Explanation #
You were given the following code:
var assignment = new Assignment();
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
var mathAssignment = assignment.make(assignmentBuilder);
mathAssignment.announcement();
You had to complete the code implementation of this program. From the first line, we know that we need to have a class Assignment
that accepts no parameters. So let’s declare that first.
function Assignment() {}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
The code above code gives an error since some other functions/methods being used are still not defined. So let’s move on to the next line.
var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");
From the following line, we know that there is a class AssignmentBuilder
which accepts the subject, the difficulty level, and the date of submission of assignment as parameters. This also means this class has these parameters defined in it, which are set when the corresponding arguments are passed to it.
function Assignment() {}function AssignmentBuilder(subject,level,dueDate) {this.subject = subject;this.level = level;this.dueDate = dueDate;}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
Now, we get an error that the make
function is not defined. Let’s understand what the make
function is doing.
make
is called on the assignment
variable and accepts the assignmentBuilder
as a parameter; meaning, it is defined in the Assignment
class so let’s define it first.
function Assignment() {this.make = function(builder){}}function AssignmentBuilder(subject,level,dueDate) {this.subject = subject;this.level = level;this.dueDate = dueDate;}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
We defined make
and passed a builder
parameter to it. In the example above, we are passing assignmentBuilder
to it, which contains an object with the three properties: subject
, level
, and dueDate
initialized to corresponding values.
function Assignment() {this.make = function(builder){}}function AssignmentBuilder(subject,level,dueDate) {this.subject = subject;this.level = level;this.dueDate = dueDate;}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");console.log(assignmentBuilder)//commneting the lines below to avoid error//var mathAssignment = assignment.make(assignmentBuilder);//mathAssignment.announcement();
From the variable name mathAssignment
we can tell that the make
function takes the AssignmentBuilder
to create a math assignment specifically. So instead of returning an object AssignmentBuilder
should return an assignment which the make
will create. Let’s modify our code:
function Assignment() {this.make = function(builder){}}function AssignmentBuilder(subject,level,dueDate) {let assignment = null;this.subject = subject;this.level = level;this.dueDate = dueDate;return assignment;}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
assignment
should have the subject
, level
, and dueDate
properties in it. For that to happen assignment
should be an object containing these properties. How about we divide this task into two steps. Let’s create a Task
class that contains these properties. An instance of this class can be stored in assignment
. So let’s modify the code accordingly.
function Assignment() {this.make = function(builder){}}function AssignmentBuilder(subject,level,dueDate) {let assignment = new Task();this.subject = subject;this.level = level;this.dueDate = dueDate;return assignment;}//creating the Task class with relevant propertiesfunction Task() {this.subject = null;this.level = null;this.dueDate = null;}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
Now we need to set the properties for the assignment
. So let’s define add functions for these properties in Task
.
function Assignment() {this.make = function(builder){}}function AssignmentBuilder(subject,level,dueDate) {//step 1let assignment = new Task();//step 2this.assignment.addSubject(subject);//step3this.assignment.addLevel(level);//step 4this.assignment.addDuedate(dueDate);return assignment;}//creating the Task class with relevant propertiesfunction Task() {this.subject = null;this.level = null;this.dueDate = null;this.addSubject = function(subject) {this.subject = subject;};this.addLevel = function(level) {this.level = level;};this.addDuedate = function(dueDate){this.dueDate = dueDate;}}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
When run the code above, you get the following error:
"Cannot read property 'addSubject' of undefined"
Since Task
initialized all properties to null
you get this error. This is where we can utilize make
. Recall make
accepts an AssignmentBuilder
object and creates a specific assignment. Keeping in mind that we are implementing the builder pattern we can change our code as follows:
function Assignment() {this.make = function(builder){//calling the steps for the builder objectbuilder.step1();builder.step2();builder.step3();builder.step4();}}//converting the steps to functionsfunction AssignmentBuilder(subject,level,dueDate) {let assignment = null;//step 1this.step1 = function() {this.assignment= new Task();};//step 2this.step2 = function() {this.assignment.addSubject(subject);};//step 3this.step3 = function(){this.assignment.addLevel(level);}//step 4this.step4 = function(){this.assignment.addDuedate(dueDate);}this.get = function(){return this.assignment;}}//creating the Task class with relevant propertiesfunction Task() {this.subject = null;this.level = null;this.dueDate = null;this.addSubject = function(subject) {this.subject = subject;};this.addLevel = function(level) {this.level = level;};this.addDuedate = function(dueDate){this.dueDate = dueDate;}}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
We simply introduced steps in the form of functions in AssignmentBuilder
. And then we called these steps in our make
function. Next, we need to move the announcement
function. From the code, we can see that it’s invoked on mathAssignment
variable which is storing the output returned from the make
function, i.e., the Task
object. Hence, we will move it there.
function Assignment() {this.make = function(builder){builder.step1();builder.step2();builder.step3();builder.step4();return builder.get();}}function AssignmentBuilder(subject,level,dueDate) {this.assignment = null;this.step1 = function() {this.assignment= new Task();};this.step2 = function() {this.assignment.addSubject(subject);};this.step3 = function(){this.assignment.addLevel(level);}this.step4 = function(){this.assignment.addDuedate(dueDate);}this.get = function() {return this.assignment;};}function Task() {this.subject = null;this.level = null;this.dueDate = null;this.addSubject = function(subject) {this.subject = subject;};this.addLevel = function(level) {this.level = level;};this.addDuedate = function(dueDate){this.dueDate = dueDate;}this.announcement = function(){console.log(`Your ${this.subject} assigment is ${this.level} and due on ${this.dueDate}.`)}}var assignment = new Assignment();var assignmentBuilder = new AssignmentBuilder("Math","hard","12th June, 2020");var mathAssignment = assignment.make(assignmentBuilder);mathAssignment.announcement();
And we’re done!!! The code produces the correct output.
Please note that this is just one of the ways to achieve this output using the builder pattern.
Let’s discuss the prototype pattern in the next lesson.