Homework - Week 14 (Design Patterns) : 1. Logger (Singleton)

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Homework - Week 14 (design patterns)

1. Logger (Singleton)

Create a ​Logger​ class:


- should have 3 methods (not static): info(String) , warn(String), error(String) -
each receives a string value and prints that value to the standard output, on one
line, and using a specific prefix ("[INFO ]"/"[WARN ]"/"[ERROR]")
- use the ​Singleton pattern​ to make sure that:
- one one Logger instance is ever created
- the instance is easily accessible to all the rest of code, in a thread-safe
manner
- write some code to test this logger class

2. Logger (Factory)

Create a ​Logger​ interface, with 3 methods (info/warn/error, similar to class from 1, each
should print the given line with a proper prefix..)

Create 2 different implementations for it:


- ConsoleLogger: should write log lines to standard output
- FileLogger: should write log lines to a single text file (file path can be hard-coded
in a constant, and it should create the file if missing, or else just append to it)

Create also a ​LoggerFactory​ class, which will be responsible for creating a logger
instance, of one of the available types:
- should have a getLogger(LoggerType) method, which will return a logger
implementation depending on requested type (LoggerType is an enum, currently
with 2 values, for the 2 logger types)

Then write some code to test your classes:


- it should write some lines (of different log levels: info/error/warn) using either the
console or the file logger
Note:​ your factory may build and return a new instance of Logger each time, and that is
ok, but it may also choose to just build one instance of logger of each type, and return
one of those (would be more optimal, but pay attention to make your code thread-safe)

Question1: should LoggerFactory.getLogger() be static or not? (do you need to build


any instances of LoggerFactory?.. and if you don't, how you can prevent client code to
attempt that?..)

Question2: if you need to add a new type of logger in the future (like a database logger),
what parts of your current code would need to be changed?

3. User class (Builder)

Create a ​User​ class, for representing the users of some system.


It needs to have these fields:
- username: String, mandatory
- email: String, mandatory
- firstName, lastName: String, is mandatory to have one of them set (user can
have only one or both of them set, but cannot have both missing)
- age: int, optional
- gender: an enum, optional (but if specified, must be >=14)
- address: String, optional (if specified, must be at least 8 char long)

Provide an easy/clear way for some other client code to safely build valid User object,
for all combinations of possible parameters (making sure they always give the required
one, allowing to also give any of the optional ones, and doing all needed final
validations for received values)
- Hint: use the Builder pattern :)

Write now a ​UsersBook​ class, to store and show info on a list of User objects (think of
it as the next Facebook ;) )
It should have at least 2 methods:
- void add(User... users) - for adding new User instances to current list
- void showUsers() - it will print the list of current users, one per line (hint: add
toString() method to User and use that here..)
4. Student (Adapter)

Create a ​Student​ class, having these fields (all mandatory):


- firstName, lastName - String
- age: int
- gender: enum (same like for 3)

Having a List of such Student objects, you want now to be able to easily add them to
UsersBook (from ex.3, it accepts only User objects).
How can you do that in an generic/reusable way? (hint: use Adapter pattern..)

This is a possible translation logic between the 2 types of objects:


- username: should be generated, format: "<student first name>_<student last
name>"
- user email: should be auto generated for students, based on format: "<student
first name>.<student last name>@tuiasi.ro"
- for rest of user fields, use the corresponding student field if it exists, or leave it
unset otherwise

5. Student email address (Strategy)

Regarding the way the email address is generated for each Student, while converting it
to a User, it is decided later that:
- it needs to be more flexible, so it should support a few different ways to do it (and
be able to easily add new ways in the future)
- should also allow the client code to choose a different way for each Student
object to be adapted (don't force a single way for all)

You should support for now 2 different email generation strategies, generating emails
with this format:
- strategy1: "<first letter of student first name>​.​<student last name>​@tuiasi.ro​"
- strategy2: "<student first name>​_​<student last name>​@tuiasi.ro​"
Change your adapter class from 4) so that it will receive, besides the Student to wrap,
also an instance of EmailGenerationStrategy, and then use that strategy to generate the
user email address for that student.

Question: if later you need to add a 3rd way to generate email addresses, how much of
your code would need to change?

You might also like