Mastering Core Design Patterns: Singleton, Adapter, Observer, and Factory Implementations in Java
This article introduces six fundamental design patterns—Singleton, Adapter, Observer, Simple Factory, Factory Method, and Abstract Factory—explaining their concepts, class diagrams, and providing complete Java code examples to illustrate each pattern's practical implementation.
1. Singleton Pattern
Ensures that a class has only one instance throughout the application lifecycle.
1.1 What is Singleton
The singleton class guarantees a single object at any time.
1.2 Class Diagram
1.3 Implementation Methods
Eager initialization:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() { /* do something */ }
public static Singleton getInstance() { return instance; }
}Lazy initialization:
public class SingletonClass {
private static SingletonClass instance = null;
public static synchronized SingletonClass getInstance() {
if (instance == null) {
instance = new SingletonClass();
}
return instance;
}
private SingletonClass() { }
}Double‑checked locking (thread‑safe lazy):
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}2. Adapter Pattern
Converts the interface of an existing class into another interface expected by the client, allowing incompatible classes to work together.
2.1 What is Adapter
Involves three roles: a target interface, an adaptee (the existing class), and an adapter that implements the target and holds a reference to the adaptee.
2.2 Class Diagram
2.3 Example Code
// Target interface
interface Target {
void request();
}
// Existing class with incompatible interface
class Adaptee {
void specificRequest() {
System.out.println("Adaptee provides special functionality...");
}
}
// Adapter class
class Adapter implements Target {
private Adaptee adaptee;
Adapter(Adaptee adaptee) { this.adaptee = adaptee; }
public void request() { adaptee.specificRequest(); }
}
// Client
class Client {
public static void main(String[] args) {
Target adapter = new Adapter(new Adaptee());
adapter.request();
}
}3. Observer Pattern
Defines a one‑to‑many dependency so that when the subject changes state, all its observers are automatically notified and updated.
3.1 What is Observer
Subject (Watched) maintains a list of observers and notifies them of changes.
3.2 Class Diagram
3.3 Example Code
// Observer interface
interface Watcher { void update(String str); }
// Concrete observer
class ConcreteWatcher implements Watcher {
public void update(String str) { System.out.println(str); }
}
// Subject interface
interface Watched {
void addWatcher(Watcher w);
void removeWatcher(Watcher w);
void notifyWatchers(String str);
}
// Concrete subject
class ConcreteWatched implements Watched {
private List<Watcher> list = new ArrayList<>();
public void addWatcher(Watcher w) { list.add(w); }
public void removeWatcher(Watcher w) { list.remove(w); }
public void notifyWatchers(String str) {
for (Watcher w : list) { w.update(str); }
}
}
// Test
class Test {
public static void main(String[] args) {
Watched subject = new ConcreteWatched();
Watcher w1 = new ConcreteWatcher();
Watcher w2 = new ConcreteWatcher();
subject.addWatcher(w1);
subject.addWatcher(w2);
subject.notifyWatchers("Update received");
}
}4. Simple Factory Pattern
Provides a static method to create instances based on input parameters, encapsulating object creation.
4.1 What is Simple Factory
The factory decides which concrete product to instantiate.
4.2 Class Diagram
4.3 Example Code
class OperationFactory {
public static Operation createOperate(String op) {
Operation oper = null;
switch (op) {
case "+": oper = new OperationAdd(); break;
case "-": oper = new OperationSub(); break;
case "*": oper = new OperationMul(); break;
case "/": oper = new OperationDiv(); break;
}
return oper;
}
}5. Factory Method Pattern
Each product has its own factory; factories create concrete products while adhering to the Open/Closed principle.
5.1 What is Factory Method
Separate product creation from product usage by defining an abstract creator that returns a product via a factory method.
5.2 Class Diagram
6. Abstract Factory Pattern
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
6.1 What is Abstract Factory
An abstract factory can produce multiple product types; concrete factories implement the creation of specific product families.
6.2 Class Diagram
6.3 Example Interfaces (illustrative)
// IDepartment interface
interface IDepartment { /* ... */ }
// IUser interface
interface IUser { /* ... */ }
// IFactory interface
interface IFactory {
IDepartment createDepartment();
IUser createUser();
}Concrete factories implement these methods to produce concrete department and user objects.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
