Let’s walk through how the Bridge Design Pattern can be applied in the context of Java Transactions (like JDBC, JPA, or Spring Transaction Management).
🌉 Bridge Pattern with Java Transactions
1. The Problem
In enterprise apps, transaction handling can vary:
- JDBC transactions (manual commit/rollback).
- JPA/Hibernate transactions (entity manager).
- Spring declarative transactions (via
@Transactional).
If you tightly couple your business logic to one transaction mechanism, switching or extending becomes painful.
2. Applying Bridge
We separate Abstraction (Business Service) from Implementation (Transaction Manager).
- Abstraction (BusinessService): Defines operations that need transactional support.
- Refined Abstraction: Specific services (e.g.,
PaymentService,OrderService). - Implementor (TransactionManager): Defines transaction operations (
begin,commit,rollback). - Concrete Implementors: JDBCTransactionManager, JPATransactionManager, SpringTransactionManager.
3. Example in Java
// Implementor
interface TransactionManager {
void begin();
void commit();
void rollback();
}
// Concrete Implementors
class JDBCTransactionManager implements TransactionManager {
public void begin() { System.out.println("JDBC Transaction started"); }
public void commit() { System.out.println("JDBC Transaction committed"); }
public void rollback() { System.out.println("JDBC Transaction rolled back"); }
}
class JPATransactionManager implements TransactionManager {
public void begin() { System.out.println("JPA Transaction started"); }
public void commit() { System.out.println("JPA Transaction committed"); }
public void rollback() { System.out.println("JPA Transaction rolled back"); }
}
// Abstraction
abstract class BusinessService {
protected TransactionManager txManager;
BusinessService(TransactionManager txManager) {
this.txManager = txManager;
}
abstract void performOperation();
}
// Refined Abstraction
class PaymentService extends BusinessService {
PaymentService(TransactionManager txManager) {
super(txManager);
}
@Override
void performOperation() {
txManager.begin();
try {
System.out.println("Executing payment logic...");
txManager.commit();
} catch (Exception e) {
txManager.rollback();
}
}
}
// Client
public class BridgeTransactionDemo {
public static void main(String[] args) {
BusinessService payment1 = new PaymentService(new JDBCTransactionManager());
payment1.performOperation();
BusinessService payment2 = new PaymentService(new JPATransactionManager());
payment2.performOperation();
}
}
4. Benefits
- Flexibility: Swap transaction strategies without touching business logic.
- Extensibility: Add new transaction managers (e.g., distributed transaction manager for microservices).
- Clean separation: Business services focus on domain logic, transaction managers handle persistence concerns.
5. Real-World Spring Boot Tie-In
In Spring, you could abstract PlatformTransactionManager (Spring’s transaction abstraction) as the Implementor, and your services as the Abstraction.
- Concrete implementors:
DataSourceTransactionManager,JpaTransactionManager,HibernateTransactionManager. - Your service layer just depends on the abstraction, not the concrete implementation.
👉 This way, you can design transaction-agnostic services that can run on JDBC, JPA, or even distributed transaction systems like Saga/Two-Phase Commit in microservices.
Would you like me to extend this into a Spring Boot example with PlatformTransactionManager so you can see how the Bridge pattern maps directly into real-world enterprise code?
No comments:
Post a Comment