prep

Introduction to Design Patterns

Learning Objectives

Self Study

As you read through the resources below try to answer the following questions:

  • In a sentence or two, summarise what is meant by a software design pattern.
  • Are design patterns limited to the field of software engineering? Where else might you see them?
  • How do design patterns simplify software development? Think about readability, communication, testability maintainability etc (note these categories of things to consider should be pretty familiar by now!)
  • How can design patterns be misused and what are some potential downsides arising from misuse?
  • What are some key factors to consider when deciding whether or not to use a design pattern?

Resources

Exercise

✍️Exercise 1.1

  • Choose 3 design patterns (apart from the facvtor and builder patters; we will study those in detail later!) from those listed in the catalogue and for each:
  • Summarise the intent i.e. the problem it solves and how it solves it (note we are not interested in the specifics of the implementing code here, we just want to know in words why the pattern exists)
  • Write down an example real life use case where the pattern may be useful (again we aren’t interested in code here, just summarise in words at a high level the specific scenario)
  • Write down an example of where the design pattern could be misused and potentially do more harm than good, and explain why

Reflections

Think about the following questions, make notes and be prepared to talk through your thoughts in the workshop.

  • In the above example, why did you pick your 3 patterns? Were they easiest to understand / clearly beneficial / you’ve already used them / some other reason(s)?
  • What might this tell you about those patterns? e.g. does a pattern being easier to understand mean it may deliver greater value than a more complex pattern? No right or wrong answers here!
  • What examples of software patterns have you seen already, either in this Java course or in other software development?
  • Based on what you’ve seen so far, what do you think are the main benefits of design patterns? Why?
  • And what are the main potential drawbacks?
  • Can you think of a piece of software you’ve written in the past where using a design pattern may have improved it?

The Factory Pattern(s)

Learning Objectives

Self Study

As you read through the resources below try to answer the following questions:

  • What is a static factory and why is it useful?
  • When is it not worth using a static factory? Why?
  • What are the key features of the factory method pattern? What problems does it solve? Think about: loose coupling (relates back to the last sprint on interfaces!), testability etc, especially for large codebases where a piece of functionality may be used by lots of teams beyond the one that wrote it.
  • Can you think of any code you’ve seen in other sprints that may benefit from use of the factory method pattern? Why?
  • How does the abstract factory pattern differ from the factory method pattern? When would you use one over the other? Do they have any similarities?
  • Can you think of any downsides to using the factory pattern or abstract factory pattern? Give an example of a specific situation when using either factory pattern would not be appropriate

Resources

✍️Exercise 2.1

  • Which type of factory (simple, method, abstract) would be most appropriate for the code below? Why?
  • Refactor the code to use your chosen pattern
public class NotificationService {
  public void send(String type, String message) {
      if (type.equals("EMAIL")) {
          EmailNotification notification = new EmailNotification();
          notification.send(message);
      } else if (type.equals("SMS")) {
          SMSNotification notification = new SMSNotification();
          notification.send(message);
      }
      // Adding new notification type requires modifying this class
  }
}

✍️Exercise 2.2

Write pseudocode and draw a class diagram to implement the following scenario using an appropriate factory pattern:

  • A software application that can be configured to use a Postgres or Oracle database
  • When configuring the database on app start-up there is some generic setup required when either DB platform is in use, but connecting to the database is platform specific
    • There is global configuration (you can use a static constant in the main Application class) to control whether Postgres or Oracle should be used
    • There is a main DatabaseInitializer class that is called from application start-up (i.e. in this case, a main method) with an #initalize method
    • There should be a class responsible for handling the connection, DatabaseConnector, whose behaviour is different for Postgres and Oracle, with a #connect method

✍️Exercise 2.3

Now suppose as well as the DatabaseInitializer class, there are other platform specific classes required: DatabaseAuthenticator and DatabaseEntityManager. Each of these are required by DatabaseInitializer. Rewrite or update your pseudocode and class diagram to handle this new scenario. Note you may want to try a different pattern!

✍️Exercise 2.4

A requirement comes through to also support MongoDB. What changes would you need to make in order to handle this? Update your code and diagram to reflect this.

Reflections

Think about the following questions, make notes and be prepared to talk through your thoughts in the workshop.

  • Was adding the requirement to support MongoDB easier or harder to implement when the factory pattern was already in play? Why?
    • Do the team implementing the MongoDB requirement need to know about the generic database initialising code?
    • Do they need to coordinate with the team that owns the core db initialisation code?
  • What about if we wanted to de-support Oracle - what would we need to change? (just think about this, no need to implement)
  • What are the key factors to consider when deciding to use the factory method pattern vs the abstract factory pattern? Does one lead to the other?
    • What do the terms YAGNI and KISS mean? (If you’ve not seen them before, have a look online.) How do they apply here?
  • What are the main benefits the factory pattern delivers?
    • Are there any drawbacks?

The Builder Pattern

Self Study

As you read through the resources below try to answer the following questions:

  • What is mean by the term ‘immutable’ and why is it desirable to have immutable classes in Java?
  • Can a class have more than one constructor? Are there any constraints - can you think of an example of two constructors for a class that would not be valid?
  • What problems can having either multiple, similar constructors, or constructors with lots of parameters cause?
  • How does the builder pattern help to solve these problems?
  • What do the terms ‘fluid interface’ and ‘method chaining’ mean?
  • Are there any downsides to using the builder pattern? When is it not appropriate to use?

Resources

Exercises

✍️Exercise 3.1

  • Refactor the following code to use the builder pattern:
    • Make all fields final
    • Private constructor taking a static inner Builder
    • Required params: id, name, price
    • Optional params: description, category, onOffer (default values)
    • Validation in build(): id not empty, name not empty, price > 0
  • Then use your builder to create:
    • A laptop on offer for £1000
    • A computer mouse not on offer for £20
  • And verify the fields have been set correctly in the following ways
    • Debugging and inspecting your objects post-creation directly
    • Overriding the toString method and printing the output to the console
public class Product {
    private String id;
    private String name;
    private double price;
    private String description;
    private String category;
    private boolean onOffer; 
    
    public Product(String id, String name, double price) { }
    public Product(String id, String name, double price, String description) { }
  
}

✍️Exercise 3.2

  • Add two new fields to your Product class, one mandatory, one optional, and update your laptop and mouse to use them

Reflections

Think about the following questions, make notes and be prepared to talk through your thoughts in the workshop.

  • What are the main advantages and potential disadvantages of the builder pattern?
    • Think of an example where the builder pattern would not be appropriate
  • Is there a factory alternative that may be used in some instances for classes with several similar constructors?
    • When would you prefer this to the builder pattern?
  • What happens if you forget a required parameter in a builder built class?
  • Why should the fields be final and what benefits does this bring?
  • Bonus: In the example above we store a monetary amount as a double - what are some potential problems with this? In general is there a preferred approach for modelling money in Java?
    • Similarly, can you think of a more appropriate type to model the product category?