Factory Pattern: Vending Machine
FACTORY PATTERN:
Implementation Steps
1. Abstract Product (Interface): Defines the structure for Beverage.
2. Concrete Products: Coffee and Tea implement the Beverage interface.
(Concrete implementation of Beverage)
3. Abstract Factory (Creator): Beverage Factory declares methods to create
beverages.
4. Concrete Factories: CoffeeFactory and TeaFactory implement
BeverageFactory.
5. Client: Uses the factory without knowing the concrete class.
General Syntax:
Factory Pattern Implementation Steps with Code:
Step 1: Define the Product Interface (Abstract Product)
public interface Product {
void doStuff();
}
Step 2: Implement Concrete Product Classes (Concrete Products)
public class ConcreteProductA implements Product {
@Override
public void doStuff() {
System.out.println("ConcreteProductA is doing stuff.");
}
}
public class ConcreteProductB implements Product {
@Override
System.out.println("ConcreteProductB is doing stuff.");
}
}
Step 3: Define the Abstract Creator (Abstract Factory)
public abstract class Creator {
public abstract Product createProduct();
public void someOperation() {
Product product = createProduct();
product.doStuff();
}
}
Step 4: Implement Concrete Factories (Concrete Factories)
public class ConcreteCreatorA extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB extends Creator {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
Step 5: Client Code
public class FactoryPatternDemo {
public static void main(String[] args) {
Creator factoryA = new ConcreteCreatorA();
factoryA.someOperation();
Creator factoryB = new ConcreteCreatorB();
factoryB.someOperation();
}
}
Expected Output:
ConcreteProductA is doing stuff.
ConcreteProductB is doing stuff.
// 1. Abstract Product
interface Beverage {
void prepare();
void serve();
}
// 2. Concrete Products
class Tea implements Beverage {
public void prepare() {
System.out.println("Boiling water...");
System.out.println("Steeping tea...");
System.out.println("Pouring tea into cup...");
}
public void serve() {
System.out.println("Dispensing: Tea");
}
}
class Coffee implements Beverage {
public void prepare() {
System.out.println("Boiling water...");
System.out.println("Brewing coffee...");
System.out.println("Pouring coffee into cup...");
}
public void serve() {
System.out.println("Dispensing: Coffee");
}
}
// 3. Abstract Factory
abstract class BeverageFactory {
abstract Beverage createBeverage();
}
// 4. Concrete Factories
class TeaFactory extends BeverageFactory {
public Beverage createBeverage() {
return new Tea();
}
}
class CoffeeFactory extends BeverageFactory {
public Beverage createBeverage() {
return new Coffee();
}
}
// 5. Client
class VendingMachine {
public Beverage orderBeverage(String choice) {
BeverageFactory factory;
// Factory selection
if(choice.equalsIgnoreCase("TEA")) {
factory = new TeaFactory();
} else if(choice.equalsIgnoreCase("COFFEE")) {
factory = new CoffeeFactory();
} else {
throw new IllegalArgumentException("Unknown choice: " + choice);
}
// Create product through factory
Beverage drink = factory.createBeverage();
// Prepare and serve
drink.prepare();
drink.serve();
return drink;
}
}
// 6. Main Program
public class Main {
public static void main(String[] args) {
VendingMachine vm = new VendingMachine();
// You ask for Coffee
vm.orderBeverage("COFFEE");
}
}
Abstract Factory:
AbstractFactory (Interface)
Declares abstract methods createProductA() and createProductB().
Defines a contract for concrete factories to implement.
ConcreteFactory1 and ConcreteFactory2
Implement the AbstractFactory interface.
Provide implementations for createProductA() and createProductB().
Each concrete factory creates a specific family of products.
AbstractProductA and AbstractProductB
Define abstract base classes (or interfaces) for product types.
Ensure that all product variants follow a common structure.
ConcreteProductA1, ConcreteProductA2, ConcreteProductB1,
ConcreteProductB2
Implement the abstract product interfaces.
Each concrete class represents a specific variant of a product.
Concrete factories instantiate these specific product implementations.
Client
Maintains a reference to an AbstractFactory object.
Calls factory methods (createProductA() and createProductB()) to create
products.
Uses the created products without knowing their exact concrete types.
Program Flow
1. The client receives an instance of an AbstractFactory.
2. The client calls createProductA() or createProductB(), which delegates
creation to a ConcreteFactory.
3. The ConcreteFactory returns an instance of a ConcreteProduct that
matches the requested type.
4. The client interacts with the products via their abstract interfaces, ensuring
flexibility and interchangeability.
Syntax:
Step 1: Define Abstract Product Interfaces
Create abstract classes or interfaces for product families.
// Abstract Product A
public interface ProductA {
void operationA();
// Abstract Product B
public interface ProductB {
void operationB();
Step 2: Create Concrete Product Implementations
Implement different variants of each product.
// Concrete Product A1
public class ConcreteProductA1 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA1 operationA");
// Concrete Product A2
public class ConcreteProductA2 implements ProductA {
@Override
public void operationA() {
System.out.println("ConcreteProductA2 operationA");
// Concrete Product B1
public class ConcreteProductB1 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB1 operationB");
// Concrete Product B2
public class ConcreteProductB2 implements ProductB {
@Override
public void operationB() {
System.out.println("ConcreteProductB2 operationB");
Step 3: Define Abstract Factory Interface
Define an interface for creating abstract product families.
// Abstract Factory
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
Step 4: Implement Concrete Factories
Each concrete factory creates a family of related products.
// Concrete Factory 1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
// Concrete Factory 2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
Step 5: Implement the Client
The client interacts with factories and products through abstract interfaces.
// Client class
public class Client {
private ProductA productA;
private ProductB productB;
public Client(AbstractFactory factory) {
productA = factory.createProductA();
productB = factory.createProductB();
public void execute() {
productA.operationA();
productB.operationB();
public static void main(String[] args) {
// Using Factory 1
AbstractFactory factory1 = new ConcreteFactory1();
Client client1 = new Client(factory1);
client1.execute();
// Using Factory 2
AbstractFactory factory2 = new ConcreteFactory2();
Client client2 = new Client(factory2);
client2.execute();
Step 6: Test and Run
When executed, this will produce the following output:
ConcreteProductA1 operationA
ConcreteProductB1 operationB
ConcreteProductA2 operationA
ConcreteProductB2 operationB
Example:
1. A global fast-food chain operates in different countries, and each
country has variations in its menu based on local preferences. For
example:
USA Menu: Cheeseburger, French Fries, Coke
India Menu: Veg Burger, Masala Fries, Mango Lassi
The challenge is to design a system that allows customers to order meals without
worrying about regional differences, while ensuring the correct menu items
are served based on the location.
2. A global beverage company produces Tea and Coffee, but their
flavors differ by region:
USA Menu: Black Coffee, Lemon Tea
India Menu: Masala Chai, Filter Coffee
The company wants a system where customers can order a beverage
without worrying about regional variations, ensuring the right drinks
are served based on the location.
3. A logistics company provides two types of transport services:
1. Road Transport – Using Trucks
2. Air Transport – Using Cargo Planes
However, the transportation methods differ based on the region:
Domestic Logistics: Uses Small Trucks and Regional Cargo Planes
International Logistics: Uses Large Trucks and International Cargo Planes
The company wants to standardize the transport selection process while ensuring
the correct vehicles are used based on the shipment type.