Abstract factory pattern java example

Java Abstract Factory Pattern example

The Abstract Factory Design Pattern is a creational pattern. It’s main purpose is to provide a way to create a related set of concrete objects without knowing about their concrete implementation. Actually the application should also be implemented against an abstract factory interface without even knowing about the factory implementation.

Usually the concrete factory implementation is provided to the application at runtime. Since the abstract factory should always provide (or build) objects in the form of interfaces, the application will become completely decoupled from both the factory and the business objects concrete implementation.

One may notice that, since the concrete factory implementation is provided to the application at runtime, we are actually injecting the factory as a dependency into the application. The abstract factory pattern is very common in applications that rely in the Dependency Injection paradigm.

In this article we will build a simple example consisting on an abstract factory that will create illustrative connections to a database.

The database connection

Our abstract factory will be able to produce database connections. Let’s define the connection interface:

package com.byteslounge.db.connection; public interface Connection

And now a couple of illustrative concrete implementations:

package com.byteslounge.db.connection; public class MySqlConnection implements Connection < @Override public void connect() < System.out.println("Connecting to MySQL. "); >>
package com.byteslounge.db.connection; public class PostgreSqlConnection implements Connection < @Override public void connect() < System.out.println("Connecting to PostgreSQL. "); >>

The abstract factory

Now let’s define the abstract connection factory interface:

Читайте также:  Adding images to html email

package com.byteslounge.db.connection.factory; import com.byteslounge.db.connection.Connection; public interface ConnectionFactory

And now a couple of concrete factory implementations, one for each of the connection types we are building (MySQL and PostgreSQL):

package com.byteslounge.db.connection.factory; import com.byteslounge.db.connection.Connection; import com.byteslounge.db.connection.MySqlConnection; public class MySqlConnectionFactory implements ConnectionFactory < @Override public Connection getConnection() < return new MySqlConnection(); >>
package com.byteslounge.db.connection.factory; import com.byteslounge.db.connection.Connection; import com.byteslounge.db.connection.PostgreSqlConnection; public class PostgreSqlConnectionFactory implements ConnectionFactory < @Override public Connection getConnection() < return new PostgreSqlConnection(); >>

Now that we have everything set, we may use the abstract factory to create connections within the application.

A sample application

We may now define an illustrative application that will use an injected factory implementation:

package com.byteslounge.application; import com.byteslounge.db.connection.Connection; import com.byteslounge.db.connection.factory.ConnectionFactory; public class Application < private final ConnectionFactory connectionFactory; public Application(ConnectionFactory connectionFactory) < this.connectionFactory = connectionFactory; >public void start() < Connection connection = connectionFactory.getConnection(); connection.connect(); // proceed with application execution. >>

As we can see the application is completely decoupled from both the connection factory and the database connections concrete implementations. The application only knows that it will receive some factory that will produce database connections.

Testing

Finally we create a runnable class in order to test the application:

package com.byteslounge; import com.byteslounge.application.Application; import com.byteslounge.db.connection.factory.ConnectionFactory; import com.byteslounge.db.connection.factory.MySqlConnectionFactory; import com.byteslounge.db.connection.factory.PostgreSqlConnectionFactory; public class Main < public static void main(String[] args) < // We should fetch the database type from an // external resource (ex: configuration file). // In order to keep this example simple we will // use a private static method and an Enum DatabaseType databaseType = DatabaseType.MYSQL; ConnectionFactory connectionFactory = getConnectionFactory(databaseType); Application application = new Application(connectionFactory); application.start(); >private static ConnectionFactory getConnectionFactory( DatabaseType databaseType) < switch (databaseType) < case MYSQL: return new MySqlConnectionFactory(); default: return new PostgreSqlConnectionFactory(); >> private enum DatabaseType < MYSQL, POSTGRE; >>

The database type could be configured in an external resource, like a properties file. The client would then create a concrete factory implementation from the external configuration file and inject it into the application.

To keep this example simple we used a static method that creates the concrete factory implementation based on an Enum.

Since we are creating a MySQL factory implementation and passing it into the application, the following output will be generated when the sample is executed:

Encapsulation

A final note about encapsulation: In this example we defined an abstract factory that produces only database connections. We could have defined our factory at a higher level (like a database driver) and use it to produce all sorts of low level database artifacts, like connections, transactions, prepared statements among others.

The concrete factories would then produce the database artifacts for each distinct database type they implement. By using this paradigm we are clearly also providing an higher level of encapsulation, since our abstract factory (and its concrete implementations) would encapsulate all the the database related artifacts production.

Download source code from this article

Источник

Abstract Factory Pattern in Java

announcement - icon

The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.

To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.

Connect your cluster and start monitoring your K8s costs right away:

We rely on other people’s code in our own work. Every day.

It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.

The problem is, of course, when things fall apart in production — debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky.

Lightrun is a new kind of debugger.

It’s one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics.

Learn more in this quick, 5-minute Lightrun tutorial:

announcement - icon

Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.

The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.

Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.

Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:

announcement - icon

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.

The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

announcement - icon

The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.

To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.

Connect your cluster and start monitoring your K8s costs right away:

We’re looking for a new Java technical editor to help review new articles for the site.

1. Overview

In this article, we’ll discuss the Abstract Factory design pattern.

The book Design Patterns: Elements of Reusable Object-Oriented Software states that an Abstract Factory “provides an interface for creating families of related or dependent objects without specifying their concrete classes”. In other words, this model allows us to create objects that follow a general pattern.

An example of the Abstract Factory design pattern in the JDK is the newInstance() of javax.xml.parsers.DocumentBuilderFactory class.

2. Abstract Factory Design Pattern Example

In this example, we’ll create two implementations of the Factory Method Design pattern: AnimalFactory and ColorFactory.

After that, we’ll manage access to them using an Abstract Factory AbstractFactory:

updated abstract factory

First, we’ll create a family of Animal class and will, later on, use it in our Abstract Factory.

Here’s the Animal interface:

and a concrete implementation Duck:

public class Duck implements Animal < @Override public String getAnimal() < return "Duck"; >@Override public String makeSound() < return "Squeks"; >> 

Furthermore, we can create more concrete implementations of Animal interface (like Dog, Bear, etc.) exactly in this manner.

The Abstract Factory deals with families of dependent objects. With that in mind, we’re going to introduce one more family Color as an interface with a few implementations (White, Brown,…).

Now that we’ve got multiple families ready, we can create an AbstractFactory interface for them:

public interface AbstractFactory

Next, we’ll implement an AnimalFactory using the Factory Method design pattern that we discussed in the previous section:

public class AnimalFactory implements AbstractFactory  < @Override public Animal create(String animalType) < if ("Dog".equalsIgnoreCase(animalType)) < return new Dog(); >else if ("Duck".equalsIgnoreCase(animalType)) < return new Duck(); >return null; > > 

Similarly, we can implement a factory for the Color interface using the same design pattern.

When all this is set, we’ll create a FactoryProvider class that will provide us with an implementation of AnimalFactory or ColorFactory depending on the argument that we supply to the getFactory() method:

public class FactoryProvider < public static AbstractFactory getFactory(String choice)< if("Animal".equalsIgnoreCase(choice))< return new AnimalFactory(); >else if("Color".equalsIgnoreCase(choice)) < return new ColorFactory(); >return null; > >

3. When to Use Abstract Factory Pattern:

  • The client is independent of how we create and compose the objects in the system
  • The system consists of multiple families of objects, and these families are designed to be used together
  • We need a run-time value to construct a particular dependency

While the pattern is great when creating predefined objects, adding the new ones might be challenging. To support the new type of objects will require changing the AbstractFactory class and all of its subclasses.

4. Summary

In this article, we learned about the Abstract Factory design pattern.

Finally, as always, the implementation of these examples can be found over on GitHub.

announcement - icon

Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.

The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.

Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.

Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:

Источник

Оцените статью