Creational Patterns#
Creational patterns: These are patterns for creating objects, abstracting the process of instantiation. They focus on the creation of objects, encapsulating the process of object creation, allowing client programs to use objects without concerning themselves with the logic of the creation process.
Simple Factory Pattern#
Simple Factory Pattern: Also known as Static Factory Method pattern, in the Simple Factory Pattern, you can return instances of different classes based on different parameters (for example, a button returns different shapes based on the shape parameter). The Simple Factory Pattern specifically defines a class responsible for creating instances of other classes, which usually share a common parent class.
Implementation Method#
-
Factory Class: Responsible for creating corresponding product objects based on input parameters (such as strings, enums, etc.).
public class VendorFactory { public static IVender createVendor(String type) { switch (type) { case "A": return new VendorA(); case "B": return new VendorB(); default: throw new RuntimeException("Supplier does not exist"); } } }
-
Abstract Product: Defines the common interface for all products.
public interface IVender { void order(); }
-
Concrete Product: Classes that implement the abstract product interface, with each class corresponding to a type of product.
public class VendorA implements IVender { @Override public void order() { System.out.println("Order placed successfully by Supplier A"); } }
Usage#
IVender vendor = VendorFactory.createVendor("A");
vendor.order(); // Output: Order placed successfully by Supplier A
Factory Method Pattern#
The core idea is to abstract the object creation process, allowing subclasses to decide which specific class to instantiate, thereby extending system functionality without modifying client code.
Components#
- Abstract Factory (Creator)
- Concrete Factory (Concrete Creator)
- Abstract Product (Product)
- Concrete Product (Concrete Product)
Implementation#
// Abstract Product
interface Car {
void show();
}
// Concrete Product
class CarA implements Car {
@Override
public void show() { System.out.println("Xiaomi SU7"); }
}
// Abstract Factory
abstract class Factory {
public abstract Car createCar();
}
// Concrete Factory
class CarFactoryA extends Factory {
@Override
public Car createCar() { return new CarA(); }
}
Implementation Method#
-
Factory Class: Responsible for creating corresponding product objects based on input parameters (such as strings, enums, etc.).
public class VendorFactory { public static IVender createVendor(String type) { switch (type) { case "A": return new VendorA(); case "B": return new VendorB(); default: throw new RuntimeException("Supplier does not exist"); } } }
-
Abstract Product: Defines the common interface for all products.
public interface IVender { void order(); }
-
Concrete Product: Classes that implement the abstract product interface, with each class corresponding to a type of product.
public class VendorA implements IVender { @Override public void order() { System.out.println("Order placed successfully by Supplier A"); } }
Usage#
IVender vendor = VendorFactory.createVendor("A");
vendor.order(); // Output: Order placed successfully by Supplier A
Abstract Factory Pattern#
Generally, a concrete factory has only one factory method or a set of overloaded factory methods. However, sometimes we need a factory that can provide multiple product objects, rather than a single product object.
Application Conditions
The Abstract Factory Pattern is needed when the specific products that the factory needs to produce are not simple objects, but multiple specific products belonging to different types in different product hierarchy structures.
The Factory Method Pattern targets a single product hierarchy, while the Abstract Factory Pattern must deal with multiple product hierarchies. A factory hierarchy can be responsible for creating product objects from multiple different product hierarchies. When a factory hierarchy can create all objects in a product family that belongs to different product hierarchies, the Abstract Factory Pattern is simpler and more efficient than the Factory Method Pattern.
Pattern Structure#
- AbstractFactory: Abstract Factory
- ConcreteFactory: Concrete Factory
- AbstractProduct: Abstract Product
- Product: Concrete Product
[Example](Abstract Factory Pattern (Easy to Understand) - CSDN Blog)
Prototype Pattern#
Creates new objects by copying existing objects (prototypes) rather than instantiating them through traditional constructors. It is particularly suitable for scenarios that require efficient creation of complex objects or dynamically generating similar objects.
Components#
- Abstract Prototype: Defines the interface for the clone method (e.g.,
Cloneable
interface). - Concrete Prototype: Specific objects that implement the cloning logic (e.g., overriding the
clone()
method). - Client: Creates new objects by calling the clone method of the prototype object.
Cloning Methods: Shallow copy, deep copy (via implementation or serialization).
Implementation#
// Abstract Prototype (implements Cloneable interface)
public abstract class Shape implements Cloneable {
protected String type;
public abstract void draw();
@Override
public Shape clone() {
try {
return (Shape) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // Will not happen
}
}
}
// Concrete Prototype: Circle
public class Circle extends Shape {
public Circle() {
type = "Circle";
}
@Override
public void draw() {
System.out.println("Drawing Circle");
}
}
// Client call
Shape original = new Circle();
Shape clone = original.clone(); // Clone object
clone.draw(); // Output: Drawing Circle
Singleton Pattern#
Ensures that a class has only one instance throughout the application lifecycle and provides a global access point. The Singleton Pattern helps avoid resource waste and data inconsistency issues caused by multiple instances.
How to ensure there is only one singleton:
Let the class itself be responsible for maintaining its unique instance. This class can ensure that no other instances are created and can provide a method to access that instance. This is the motivation behind the Singleton Pattern.
Implementation Method#
Lazy Initialization (created only when first called)
public class Singleton {
private static Singleton instance;
private Singleton() {
// Private constructor
}
public static Singleton getInstance() {
if (instance == null) { // First check
instance = new Singleton();
}
return instance;
}
}
Eager Initialization (instance created when class is loaded)
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {
// Private constructor
}
public static Singleton getInstance() {
return instance;
}
}