Lab 4: The builder and factory method design patterns
The goal of this lab is to apply two creational design patterns: the builder and factory method design patterns.
Design patterns are proven solutions to solve recurring design problems to design flexible and reusable object-oriented software; that is, objects that are easier to implement, change, test and reuse.
The builder design pattern and factory method design pattern are two of the twenty-three well-known Gang of Four (GoF) design patterns. They are classified as creational patterns since both patterns provide an elegant and an efficient way to create an object.
The builder pattern is used to build and construct a complex object in a step by step approach. It’s especially helpful when the creation of an object involves a set of required and optional parameters. Instead of using constructor overloading or telescoping constructor (i.e., the use of more than one constructor in an instance class), the builder design pattern solves this problem in an elegant way allowing us to create different representations of an object. The builder design pattern solves the problem of creating complete objects step by step without having to rely on constructor overloading and passing nulls for unused parameters.
The factory method design pattern is another creational design pattern that deals with the problem of creating objects without having to specify the exact class of the object that will be created. This done by a separate operation (factory method) for creating an object. Creating an object by calling a factory method helps avoid tight coupling between the creator and the concrete classes.
Video
Objectives
In this lab you will
understand a real-world scenario and choose when to apply the appropriate design pattern.
design and implement the builder design pattern.
design and implement the factory method design pattern.
write unit tests and apply Test-Driven Development (TDD).
If your instructor is using GitHub classroom, you will need to accept the assignment using the link below, clone the template repository, and import it as a project into your IDE.
A developer is working on a game that features characters from the famed fantasy novel, the Lord of the Rings ↗. She’s working on a feature that allows users to create avatars that reflect and represent the characters in the novel. An avatar is a graphical representation of a user or a user’s character. The creation of an avatar is inherently a step-by-step process. You start with a skin tone and additional facial features such as hair, eye brows, mustache, eyeglasses each of which has different styles. This feature is inspired by the highly customized and inclusive feature of creating an avatar in the Snapchat app, which is also named a Bitmoji and shown below.
She started working on three characters: Aragorn, Legolas, and Frodo Baggins. These characters will be represented by three avatars: Knight, Archer, and Ring Flag Bearer respectively. These avatars can be customized with different skin tones, hair colors, hair types, body types and a set of facial features.
She started implementing this avatar feature by writing an interface for the Characters and a concrete class for each avatar.
publicclassKnightimplements Characters {private String name;private Avatar avatar;publicKnight(String name){if(name ==null){thrownew IllegalArgumentException("Character must have a name");}this.name=name;this.avatar=new Avatar(SkinTone.MEDIUM, HairType.LONG_STRAIGHT, HairColor.BLACK, BodyType.MUSCULAR, FacialFeatures.LIGHT_BEARD);}public String getName(){returnthis.name;}public Avatar getAvatar(){returnthis.avatar;}publicvoidsetName(String name){this.name=name;}publicvoidsetAvatar(Avatar avatar){this.avatar=avatar;}public String toString(){returnthis.name+" has "+this.avatar.toString();}}
Next, she defined a set of enums for skin tones, hair types, hair colors, body types, and facial features. You can think of an enum as a special “class” that represents a group of constants-like final variables.
Now, she wrote the initial implementation of the Avatar class as shown below. Note that she used constructor overloading for the Avatar class where one constructor contains a set of required parameters, another one with one optional parameter, a third with two optional parameters, and so on, culminating in a constructor with all the optional parameters.
This implementation is often known as the telescoping constructor pattern, in which you provide a constructor with only the required parameters, another with a single optional parameter, a third with two optional parameters, and so on. While this implementation works, it does not scale well to large numbers of optional parameters. It is also difficult to remember to the order of required parameters and know what default values are used for optional parameters. It is also hard to read as you’re always left wondering what the order of parameters is, and you need to carefully count parameters to find out which constructor to call. More importantly, this will require adding additional constructors in the future to handle additional combinations and any changes to the order of parameters will break all clients in the three characters Knight, Archer, and FlagBearer.
Enter the Builder design pattern!
The builder pattern is intended to solve this problem in an elegant way allowing us to create different representations of an object and create objects in a step-by-step manner without having to rely on constructor overloading and passing defaults for unused parameters. This pattern is flexible and it is easy to add more parameters to it in the future. This especially important because in this scenario, creating an Avatar, we suspect tp add more parameters in the future. This design pattern feature a common programming syntax called “Method Chaining”, where a method is used to invoke multiple methods on the same object in a single Java statement.
Questions
Question 1: Fix the current implementation of the Avatar class using the builder design pattern and remove the constructors overloading (telescoping constructor).
Question: 2 Complete the code in the CharacterFactory class to have a factory method that creates an Avatar by it’s character type (e.g., Knight, Archer, and FlagBearer) and assigns a name to the character (e.g., Aragorn, Legolas, and Frodo Baggins).
publicclassCharacterFactory{// A factory method that returns an object (Archer, FlagBearer, or Knight) by its name
publicstatic Characters createCharacter(CharacterTypes type, String name){}}
If your instructor is using GitHub classroom, then you should click on your class submission link,
link your GitHub username to your name if you have not already done so, accept the assignment, clone the
repository into your local
development environment, and push the code to the remote repository on GitHub. Please make sure that your
written
answers are included in either a README (Markdown) file or a PDF file.
Lab dues dates are listed on GitHub classroom unless otherwise
noted.
If your instructor is using GitHub classroom, your submission will be
auto-graded
by running the included unit tests as well as manually graded for correctness, style, and quality.
How to submit your lab to GitHub Classroom
The video below demonstrates how to submit your work to GitHub classroom
Extra Task [Optional]
If you are done with this activity, you may enable a continuos integration tool such as CircleCI ↗ to automatically run your JUnit test upon code changes. You may also add more unit tests to increase code coverage. Please embed the badge that shows the status of your build and test (passing/failing) as well as the coverage percentage into your README file (e.g.,
and ). Please be sure to fork the repository or push to a remote repository under your own account, so you can enable the integration of CI tools in your own account.