Java factory classes example

Java Factory Pattern Explained

What is the most usual method of creating an instance of a class in java? Most people will answer this question: “using new keyword“. Well, it is considered old-fashioned now. Let’s see how??

If object creation code is spread in the whole application, and if you need to change the process of object creation then you need to go in each and every place to make necessary changes. After finishing this article, while writing your application, consider using the Java factory pattern.

In my previous post, “Singleton design pattern in java“, we discussed various ways to create an instance of a class such that there can not exist another instance of same class in same JVM.

In this post, I will demonstrate another creational pattern, i.e. Factory pattern, for creating instances for your classes. Factory, as the name suggests, is a place to create some different products which are somehow similar in features yet divided into categories.

In Java, factory pattern is used to create instances of different classes of the same type.

Table of Contents 1. When to implement factory pattern? 2. Factory Pattern Implementation 3. Advantages of factory pattern 4. Final notes

1. When to use factory pattern?

Factory pattern introduces loose coupling between classes which is the most important principle one should consider and apply while designing the application architecture. Loose coupling can be introduced in application architecture by programming against abstract entities rather than concrete implementations. This not only makes our architecture more flexible but also less fragile.

A picture is worth a thousand words. Let’s see how a factory implementation will look like.

class_diagram_of_factory_pattern_in_java1-8964987

Above class-diagram depicts a common scenario using an example of a car factory which is able to build 3 types of cars i.e. small, sedan and luxury. Building a car requires many steps from allocating accessories to final makeup. These steps can be written in programming as methods and should be called while creating an instance of a specific car type.

If we are unfortunate then we will create instances of car types (e.g. SmallCar ) in our application classes and thus we will expose the car building logic to the outside world and this is certainly not good. It also prevents us in making changes to car making process because the code is not centralized, and making changes in all composing classes seems not feasible.

2. Java Factory Pattern Example

So far we have design the classes need to be designed for making a CarFactory. Let’s create them now.

2.1. Object types

CarType will hold the types of car and will provide car types to all other classes.

package designPatterns.creational.factory; public enum CarType

2.2. Object implementations

Car is parent class of all car instances and it will also contain the common logic applicable in car making of all types.

package designPatterns.creational.factory; public abstract class Car < public Car(CarType model) < this.model = model; arrangeParts(); >private void arrangeParts() < // Do one time processing here >// Do subclass level processing in this method protected abstract void construct(); private CarType model = null; public CarType getModel() < return model; >public void setModel(CarType model) < this.model = model; >>

LuxuryCar is concrete implementation of car type LUXURY .

package designPatterns.creational.factory; public class LuxuryCar extends Car < LuxuryCar() < super(CarType.LUXURY); construct(); >@Override protected void construct() < System.out.println("Building luxury car"); // add accessories >>

SmallCar is concrete implementation of car type SMALL .

package designPatterns.creational.factory; public class SmallCar extends Car < SmallCar() < super(CarType.SMALL); construct(); >@Override protected void construct() < System.out.println("Building small car"); // add accessories >>

SedanCar is concrete implementation of car type SEDAN .

package designPatterns.creational.factory; public class SedanCar extends Car < SedanCar() < super(CarType.SEDAN); construct(); >@Override protected void construct() < System.out.println("Building sedan car"); // add accessories >>

2.3. Factory to create objects

CarFactory.java is our main class implemented using factory pattern. It instantiates a car instance only after determining its type.

package designPatterns.creational.factory; public class CarFactory < public static Car buildCar(CarType model) < Car car = null; switch (model) < case SMALL: car = new SmallCar(); break; case SEDAN: car = new SedanCar(); break; case LUXURY: car = new LuxuryCar(); break; default: // throw some exception break; >return car; > >

2.4. Test factory pattern

In TestFactoryPattern , we will test our factory code. Lets run this class.

package designPatterns.creational.factory; public class TestFactoryPattern < public static void main(String[] args) < System.out.println(CarFactory.buildCar(CarType.SMALL)); System.out.println(CarFactory.buildCar(CarType.SEDAN)); System.out.println(CarFactory.buildCar(CarType.LUXURY)); >>
Building small car designPatterns.creational.factory.SmallCar@7c230be4 Building sedan car designPatterns.creational.factory.SedanCar@60e1e567 Building luxury car designPatterns.creational.factory.LuxuryCar@e9bfee2

As you can see, the factory is able to return any type of car instance it is requested for. It will help us in making any kind of changes in car making process without even touching the composing classes i.e. classes using CarFactory .

Читайте также:  Использование ini файлов php

3. Benefits of factory pattern

By now, you should be able to count the main advantages of using the factory pattern. Let’s note down:

  1. The creation of an object precludes its reuse without significant duplication of code.
  2. The creation of an object requires access to information or resources that should not be contained within the composing class.
  3. The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.

Factory pattern is most suitable where there is some complex object creation steps are involved. To ensure that these steps are centralized and not exposed to composing classes, factory pattern should be used. We can see many realtime examples of factory pattern in JDK itself e.g.

I hope, I have included enough information in this Java factory pattern example to make this post informative.

If you still have some doubt on abstract factory design pattern in Java, please leave a comment. I will be happy to discuss with you.

Источник

Java factory classes example

Я понимаю что в 1м примере с кофе нужно разделить создание экземпляров от приготовления кофе. Мне не понятно, а не проще ли просто было создать метод createCoffee в этом же классе CoffeeShop, а не городить дополнительный класс? Я не настаиваю что я прав, но хочу понять что бы разобраться. public class CoffeeShop < public Coffee createCoffee (CoffeeType type) < Coffee coffee = null; switch (type) < case AMERICANO: coffee = new Americano(); break; case ESPRESSO: coffee = new Espresso(); break; case CAPPUCCINO: coffee = new Cappuccino(); break; case CAFFE_LATTE: coffee = new CaffeLatte(); break; >return coffee; > public Coffee orderCoffee(CoffeeType type) < /*Coffee coffee = null; switch (type) < case AMERICANO: coffee = new Americano(); break; case ESPRESSO: coffee = new Espresso(); break; case CAPPUCCINO: coffee = new Cappuccino(); break; case CAFFE_LATTE: coffee = new CaffeLatte(); break; >*/ Coffee coffee = createCoffee(type); coffee.grindCoffee(); coffee.makeCoffee(); coffee.pourIntoCup(); System.out.println(«Вот ваш кофе! Спасибо, приходите еще!»); return coffee; > >

Читайте также:  Already bound exception java

У данного примера с кофе, мы все также не решаем проблему маштабирования. Если у нас появляется новый вид кофе, то нам нужно вносить изменения в 2 класса SimpleCoffeeFactory и CoffeeType. «Если ассортимент изменится, нам не придется править код везде, где будет использоваться создание кофе. Достаточно будет изменить код только в одном месте.» — остается проблемой.

А как это дело запустить то? В мэйне мы же не можем создать экземпляр кофешоп. Статик сделать тоже не получается. Как вывести то в консоль что кофе готово?

 Хотя все могло быть еще проще, если сделать метод createCoffee статичным. Но тогда мы потеряли бы две возможности: 1. Наследоваться от SimpleCoffeeFactory и переопределять метод createCoffee . 

Почему не будет возможности наследоваться и тем более переопределять метод, если createCoffe будет с модификатором static?

Использовать switch тоже не совсем хорошая практика. Это претензия не к автору, почему то во всех примерах используют case. Но это как-то не красиво, да и в реальных проектах я такого не встречал

Источник

Factory method design pattern in Java

It is a creational design pattern that talks about the creation of an object. The factory design pattern says that define an interface ( A java interface or an abstract class) for creating object and let the subclasses decide which class to instantiate. The factory method in the interface lets a class defers the instantiation to one or more concrete subclasses. Since these design patterns talk about the instantiation of an object and so it comes under the category of creational design pattern. If we notice the name Factory method, that means there is a method which is a factory, and in general, factories are involved with creational stuff and here with this, an object is being created. It is one of the best ways to create an object where object creation logic is hidden from the client. Now Let’s look at the implementation.

Implementation:

  1. Define a factory method inside an interface.
  2. Let the subclass implements the above factory method and decides which object to create.
  3. In Java, constructors are not polymorphic, but by allowing subclass to create an object, we are adding polymorphic behavior to the instantiation. In short, we are trying to achieve Pseudo polymorphism by letting the subclass to decide what to create, and so this Factory method is also called a virtual constructor.

Let us try to implement it with a real-time problem and some coding exercises.

Problem Statement: Consider we want to implement a notification service through email, SMS, and push notifications. Let’s try to implement this with the help of the factory method design pattern. First, we will design a UML class diagram for this.

In the above class diagram, we have an interface called Notification, and three concrete classes are implementing the Notification interface. A factory class NotificationFactory is created to get a Notification object. Let’s jump into the coding now.

Create Notification interface

Источник

Factory Design Pattern in Java

Factory Design Pattern in Java

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Welcome to the Factory Design Pattern in Java tutorial. Factory Pattern is one of the Creational Design pattern and it’s widely used in JDK as well as frameworks like Spring and Struts.

Factory Design Pattern

factory design pattern, factory design pattern in java, factory pattern, factory method pattern, factory pattern example

The factory design pattern is used when we have a superclass with multiple sub-classes and based on input, we need to return one of the sub-class. This pattern takes out the responsibility of the instantiation of a class from the client program to the factory class. Let’s first learn how to implement a factory design pattern in java and then we will look into factory pattern advantages. We will see some of the factory design pattern usage in JDK. Note that this pattern is also known as Factory Method Design Pattern.

Читайте также:  Плагины для firefox java

Factory Design Pattern Super Class

Super class in factory design pattern can be an interface, abstract class or a normal java class. For our factory design pattern example, we have abstract super class with overridden toString() method for testing purpose.

package com.journaldev.design.model; public abstract class Computer < public abstract String getRAM(); public abstract String getHDD(); public abstract String getCPU(); @Override public String toString()< return "RAM= "+this.getRAM()+", HDD="+this.getHDD()+", CPU="+this.getCPU(); >> 

Factory Design Pattern Sub Classes

package com.journaldev.design.model; public class PC extends Computer < private String ram; private String hdd; private String cpu; public PC(String ram, String hdd, String cpu)< this.ram=ram; this.hdd=hdd; this.cpu=cpu; >@Override public String getRAM() < return this.ram; >@Override public String getHDD() < return this.hdd; >@Override public String getCPU() < return this.cpu; >> 
package com.journaldev.design.model; public class Server extends Computer < private String ram; private String hdd; private String cpu; public Server(String ram, String hdd, String cpu)< this.ram=ram; this.hdd=hdd; this.cpu=cpu; >@Override public String getRAM() < return this.ram; >@Override public String getHDD() < return this.hdd; >@Override public String getCPU() < return this.cpu; >> 

Factory Class

Now that we have super classes and sub-classes ready, we can write our factory class. Here is the basic implementation.

package com.journaldev.design.factory; import com.journaldev.design.model.Computer; import com.journaldev.design.model.PC; import com.journaldev.design.model.Server; public class ComputerFactory < public static Computer getComputer(String type, String ram, String hdd, String cpu)< if("PC".equalsIgnoreCase(type)) return new PC(ram, hdd, cpu); else if("Server".equalsIgnoreCase(type)) return new Server(ram, hdd, cpu); return null; >> 
  1. We can keep Factory class Singleton or we can keep the method that returns the subclass as static.
  2. Notice that based on the input parameter, different subclass is created and returned. getComputer is the factory method.

factory pattern java, factory pattern, factory design pattern, factory pattern class diagram

Here is a simple test client program that uses above factory design pattern implementation.

package com.journaldev.design.test; import com.journaldev.design.factory.ComputerFactory; import com.journaldev.design.model.Computer; public class TestFactory < public static void main(String[] args) < Computer pc = ComputerFactory.getComputer("pc","2 GB","500 GB","2.4 GHz"); Computer server = ComputerFactory.getComputer("server","16 GB","1 TB","2.9 GHz"); System.out.println("Factory PC Config::"+pc); System.out.println("Factory Server Config::"+server); >> 

Output of above program is:

Factory PC Config::RAM= 2 GB, HDD=500 GB, CPU=2.4 GHz Factory Server Config::RAM= 16 GB, HDD=1 TB, CPU=2.9 GHz 

Factory Design Pattern Advantages

  1. Factory design pattern provides approach to code for interface rather than implementation.
  2. Factory pattern removes the instantiation of actual implementation classes from client code. Factory pattern makes our code more robust, less coupled and easy to extend. For example, we can easily change PC class implementation because client program is unaware of this.
  3. Factory pattern provides abstraction between implementation and client classes through inheritance.

Factory Design Pattern Examples in JDK

  1. java.util.Calendar, ResourceBundle and NumberFormat getInstance() methods uses Factory pattern.
  2. valueOf() method in wrapper classes like Boolean, Integer etc.

Factory Design Pattern YouTube Video Tutorial

I recently uploaded a video on YouTube for Factory Design pattern, please check it out. Please like and share the video and subscribe to my YouTube channel. https://www.youtube.com/watch?v=J1QU\_R4MQQc

You can download the example code from my GitHub Project.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Источник

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