Skip to content

Applied Design Patterns

Jon Freer edited this page Jan 13, 2019 · 1 revision

Building effective, yet maintainable and extendable software almost always requires the use of design patterns.

It can be overwhelming when getting acquainted with a newer or larger codebase, and it can take longer to understand which components are participants within a on overarching design pattern. To help you navigate the code we have cataloged the various design patterns leveraged in noti, as well as provided concrete examples of their usage.

The abstract factory pattern provides a way to encapsulate a group of individual factories that have a common theme without specifying their concrete classes.

Usages

Representation Creation

Within a RESTful API, each request interacts with a resource using representations. These representations are different based on the content type (Content-Type, Accept, etc.), content encoding (Content-Encoding), language (Content-Language) and more.

Given the various classes in our code that are representations and the relationship amongst them, the abstract factory pattern serves as a great pattern for creating these types. It allows all code within noti that needs to create a representation to utilize two abstractions: Representation and RepresentationFactory.

Here are some of the concrete implementations of the RepresentationFactory and Representation classes:

  • RepresentationFactory
    • api.representations.json.JSONRepresentationFactory
    • api.representations.xml.XMLRepresentationFactory
    • api.representations.siren.SirenRepresentationFactory
    • api.representations.yaml.YAMLRepresentationFactory
  • Representation
    • api.representations.json.Notification
    • api.representations.xml.Audience
    • api.representations.siren.Target
    • api.representations.yaml.Message
    • etc.

You can find all of the classes the related to representation creation within the following packages:

Database Connection Creation

As software systems grow in complexity, and as the surrounding application landscape becomes increasingly diverse, it is not uncommon for multiple database technologies to be utilized by a single application.

Currently, noti only leverages a single MySQL database. However, it’s best to ensure that we are as ready as we can be if we ever need to switch to a different database technology, or perhaps leverage an additional one in parallel. To help us be prepared, we used the abstract factory design pattern for database connection creation.

We essentially have two abstractions that client code interact with: ConnectionFactory and Connection. Consumers of this pattern have no need to understand what the database technology is; simply just that it needs to create a connection.

The Connection interface is actually java.sql.Connection - we did not author it. That means the only types we needed to create here are:

  • ConnectionFactory
    • MySQLConnectionFactory

These can be found in the infrastructure package.

You could imagine that if we needed to create connections to a Postgres or Oracle databases, we would introduce corresponding concrete implementations of the ConnectionFactory abstract class: PostgresConnectionFactory and OracleConnectionFactory, respectively.

Unit of Work Creation

In the spirit of the fluctuating data storage choices, utilizing the abstract factory design pattern for our Unit of Work creation aligned well. Given that a Unit of Work is an abstraction representing a domain-related transaction, the introduction of or a switch of data storage choices would result in corresponding transaction-related implementations.

With the use of the abstract factory design pattern, client code of the Unit of Work exclusively work with the UnitOfWork and UnitOfWorkFactory abstractions. The client code has no knowledge of (and therefore, no coupling) to the more specific and concrete implementations.

The following are the types we introduced to accomplished this pattern:

  • UnitOfWorkFactory
    • SQLUnitOfWorkFactory
  • UnitOfWork
    • SQLUnitOfWork

These types can found in the infrastructure package.

Factory Method

TODO

Query Object (Interpretor)

TODO

Unit of Work

TODO

Repository

TODO

Data Mapper

TODO

Identity Map

TODO

Metadata Map

TODO

Clone this wiki locally