Java Design Pattern Snippets
This VS Code extension provides ready-to-use Java code snippets for common Gang of Four (GoF) design patterns.
Save time and stay consistent with clean and understandable Java implementations of classic design patterns.
✨ Included Patterns
- 🔒 Singleton – Ensure only one instance of a class.
- 🏭 Factory Method – Create objects based on given conditions.
- 🏗️ Abstract Factory – Create families of related objects.
- 🔄 State – Allow an object to change behavior based on internal state.
- 🎨 Decorator – Add responsibilities to objects dynamically.
- 🧠 Strategy – Define a family of interchangeable algorithms.
- 👁️ Observer – Notify multiple objects about changes in state.
🛠️ Usage
In any .java
file, just start typing the pattern prefix, for example:
singleton
→ Generates a Singleton class template.
factorymethod
→ Generates an interface and factory method implementation.
observer
→ Generates subject and observer interfaces and classes.
Press Tab
to expand the snippet and jump between editable fields.
🚀 How to Install
Search for Java Design Pattern Snippets in the Extensions view of VS Code, or install via CLI:
code --install-extension nonegroup.java-design-pattern-snippets
🧩 Snippet Prefixes
Pattern |
Prefix |
Singleton |
singleton |
Factory Method |
factorymethod |
Abstract Factory |
abstractfactory |
State |
state |
Decorator |
decorator |
Strategy |
strategy |
Observer |
observer |
1. 🔒 Singleton (Ensure a single instance)
🎯 When to use?
- When the system should only have one instance: e.g., Logging, Configuration, Connection Pool.
- Prevent unnecessary duplication.
- Provide a Global Access Point.
📐 UML
┌────────────────────────────┐
│ Singleton │
├────────────────────────────┤
│ - instance: Singleton │
│ + Singleton() │
├────────────────────────────┤
│ + getInstance(): Singleton │
│ + showMessage(): void │
└────────────────────────────┘
💻 Java Code
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void showMessage() {
System.out.println("This is Singleton!");
}
}
2. 🏭 Factory Method (Create objects based on conditions)
🎯 When to use?
- When multiple subclasses implement the same interface/abstract class, but we don't know which to instantiate.
- Decouple object creation from the client.
📐 UML
┌───────────────┐
│ BankFactory │
└───────┬───────┘
│
▼
┌───────────────┐
│ Bank │
└─────▲───▲─────┘
│ │
┌─────────┘ └─────────┐
┌────────────┐ ┌───────────────┐
│ BBank │ │ ABank │
└────────────┘ └───────────────┘
💻 Java Code
public interface Bank {
String getBankName();
}
public class BBank implements Bank {
public String getBankName() {
return "BBank";
}
}
public class ABank implements Bank {
public String getBankName() {
return "ABank";
}
}
public class BankFactory {
public static Bank getBank(String bankType) {
switch (bankType) {
case "AB": return new ABank();
case "BB": return new BBank();
default: throw new IllegalArgumentException("Unknown bank type");
}
}
}
// Client usage
Bank bank = BankFactory.getBank("BB");
System.out.println(bank.getBankName()); // BBank
🎯 When to use?
- Need to create a group of related objects without revealing their concrete classes.
- Example:
ModernFurnitureFactory
creates ModernChair
, ModernTable
.
📐 UML
┌────────────────────┐
│ AbstractFactory │
└───────┬────────────┘
│
┌─────────────┼─────────────┐
│ │ │
┌───────┐ ┌───────┐ ┌───────┐
│ Chair │ │ Sofa │ │ Table │
└───▲───┘ └──▲────┘ └──▲────┘
│ │ │
┌─────┴─────┐ ┌────┴─────┐ ┌─────┴─────┐
│ Modern │ │ Modern │ │ Modern │
└───────────┘ └──────────┘ └───────────┘
💻 Java Code
interface Chair {
void sitOn();
}
interface Table {
void putOn(String item);
}
class ModernChair implements Chair {
public void sitOn() {
System.out.println("Sitting on modern chair");
}
}
class ModernTable implements Table {
public void putOn(String item) {
System.out.println("Placing " + item + " on modern table");
}
}
interface FurnitureFactory {
Chair createChair();
Table createTable();
}
class ModernFurnitureFactory implements FurnitureFactory {
public Chair createChair() {
return new ModernChair();
}
public Table createTable() {
return new ModernTable();
}
}
// Client
FurnitureFactory factory = new ModernFurnitureFactory();
Chair c = factory.createChair();
Table t = factory.createTable();
c.sitOn();
t.putOn("Laptop");
4. 🔄 State (Behavior changes with state)
🎯 When to use?
- When an object’s behavior depends on its internal state.
- Avoid large
if-else
or switch
blocks.
📐 UML
┌────────────┐
│ Computer │
├────────────┤
│ - state │
└─────┬──────┘
│ has
▼
┌────────┐
│ State │
└──┬─┬─┬─┘
│ │ │
┌────────────┘ │ └────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ Off │ │ On │ │ Sleep │
└────────┘ └────────┘ └────────┘
💻 Java Code
interface State {
void handle(Computer computer);
}
class OffState implements State {
public void handle(Computer computer) {
System.out.println("Turning on computer...");
computer.setState(new OnState());
}
}
class OnState implements State {
public void handle(Computer computer) {
System.out.println("Computer is on, switching to Sleep...");
computer.setState(new SleepState());
}
}
class SleepState implements State {
public void handle(Computer computer) {
System.out.println("Waking up from Sleep...");
computer.setState(new OnState());
}
}
class Computer {
private State state = new OffState();
public void setState(State state) {
this.state = state;
}
public void pressPowerButton() {
state.handle(this);
}
}
// Client
Computer pc = new Computer();
pc.pressPowerButton(); // Off → On
pc.pressPowerButton(); // On → Sleep
pc.pressPowerButton(); // Sleep → On
5. 🎨 Decorator (Extend functionality without modifying original class)
🎯 When to use?
- Add features dynamically without subclassing.
📐 UML
┌───────────────────┐
│ Coffee │◄───────────┐
└─────────▲─────────┘ │
│ │
┌──────────┴──────────┐ ┌─────────┴───────────┐
│ SimpleCoffee │ │ CoffeeDecorator │
└─────────────────────┘ └─────────▲───────────┘
│
┌──────────────┴─────────────┐
│ │
┌─────────┴─────────┐ ┌─────────┴─────────┐
│ MilkDecorator │ │ SugarDecorator │
└───────────────────┘ └───────────────────┘
💻 Java Code
interface Coffee {
String getDescription();
double cost();
}
class SimpleCoffee implements Coffee {
public String getDescription() {
return "Black coffee";
}
public double cost() {
return 15000;
}
}
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee c) {
this.coffee = c;
}
public String getDescription() {
return coffee.getDescription();
}
public double cost() {
return coffee.cost();
}
}
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee c) {
super(c);
}
public String getDescription() {
return coffee.getDescription() + ", with milk";
}
public double cost() {
return coffee.cost() + 5000;
}
}
// Client
Coffee c = new SimpleCoffee();
System.out.println(c.getDescription()); // Black coffee
c = new MilkDecorator(c);
System.out.println(c.getDescription()); // Black coffee, with milk
System.out.println(c.cost());
6. 🧠 Strategy (Swap algorithms flexibly)
🎯 When to use?
- There are multiple ways to solve a problem and we want to choose one at runtime.
- E.g., payment methods: CreditCard, Paypal, Momo.
📐 UML
┌──────────────────┐
│ PaymentStrategy │
└──────┬──┬──┬─────┘
│ │ │
┌────────────────┘ │ └───────────────┐
▼ ▼ ▼
┌───────────────┐ ┌──────────────┐ ┌──────────────┐
│ CreditCardPay │ │ PaypalPay │ │ StripePay │
└───────────────┘ └──────────────┘ └──────────────┘
▲
│ uses
┌────────────────┐
│ ShoppingCart │
└────────────────┘
💻 Java Code
interface PaymentStrategy {
void pay(int amount);
}
// CreditCard implementation
class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
public CreditCardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
public void pay(int amount) {
System.out.println("Paid " + amount + " via Credit Card " + cardNumber);
}
}
// Paypal implementation
class PaypalPayment implements PaymentStrategy {
private String email;
public PaypalPayment(String email) {
this.email = email;
}
public void pay(int amount) {
System.out.println("Paid " + amount + " via Paypal account: " + email);
}
}
// Stripe implementation
class StripePayment implements PaymentStrategy {
private String accountId;
public StripePayment(String accountId) {
this.accountId = accountId;
}
public void pay(int amount) {
System.out.println("Paid " + amount + " via Stripe account: " + accountId);
}
}
// ShoppingCart context
class ShoppingCart {
private PaymentStrategy strategy;
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void checkout(int amount) {
if (strategy == null) {
System.out.println("No payment strategy selected!");
return;
}
strategy.pay(amount);
}
}
// Client
ShoppingCart cart = new ShoppingCart();
cart.setPaymentStrategy(new CreditCardPayment("1234 5678"));
cart.checkout(100000);
cart.setPaymentStrategy(new PaypalPayment("user@example.com"));
cart.checkout(200000);
cart.setPaymentStrategy(new StripePayment("acc_98765"));
cart.checkout(300000);
7. 👁 Observer (Track and update on change)
🎯 When to use?
- When many objects (Observers) need to track and react to changes in one object (Subject).
📐 UML
┌─────────────┐ ┌──────────────┐
│ Subject │ │ Observer │
├─────────────┤ ├──────────────┤
│+ register() │ 1 n │+ update() │
│+ remove() │────────► │ │
│+ notifyAll()│ └─────▲────────┘
└─────────────┘ │
│
┌─────────────────────┴─────────────────┐
│ │
┌───────────────┐ ┌───────────────┐
│ ShareHolder 1 │ │ ShareHolder 2 │
└───────────────┘ └───────────────┘
💻 Java Code
interface Observer {
void update(float price);
}
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
class ShareMarket implements Subject {
private List<Observer> observers = new ArrayList<>();
private float sharePrice;
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
for (Observer o : observers) {
o.update(sharePrice);
}
}
public void setSharePrice(float price) {
this.sharePrice = price;
notifyObservers();
}
}
class ShareHolder implements Observer {
private String name;
public ShareHolder(String name) {
this.name = name;
}
public void update(float price) {
System.out.println(name + " received new price: " + price);
}
}
// Client
ShareMarket market = new ShareMarket();
ShareHolder A = new ShareHolder("A");
ShareHolder B = new ShareHolder("B");
market.registerObserver(A);
market.registerObserver(B);
market.setSharePrice(100.5f); // A and B get notified