Structural patterns explain how to assemble objects and classes into larger structures while keeping them flexible and efficient.
Design a payment processing system that can integrate with multiple payment gateways (Stripe, PayPal, Razorpay) through a unified interface. The system should allow adding new payment providers without changing existing code.
- Relevance: Adapter pattern is crucial for integrating third-party services. Common in payment, authentication, and API integrations.
- Real-World: E-commerce platforms integrate with multiple payment gateways. Adapter pattern provides unified interface while hiding implementation differences.
- Pattern: Adapter pattern allows incompatible interfaces to work together.
Adapter acts as a bridge between two incompatible interfaces. Converts interface of a class into another interface clients expect.
PaymentGateway: Target interface (what client expects)StripeAdapter,PayPalAdapter,RazorpayAdapter: Adapters wrapping third-party APIsPaymentService: Client using unified interfaceStripeAPI,PayPalAPI: Existing incompatible interfaces
- Define
PaymentGatewayinterface with common methods (processPayment, refund) - Create adapter classes implementing
PaymentGateway - Each adapter wraps third-party API and translates calls
- Client code uses
PaymentGatewayinterface only - Support factory pattern for adapter creation
- API failures and retries
- Different error formats from providers
- Transaction idempotency
- Currency conversion handling
Design a notification system where you can add features (encryption, compression, retry logic) to notifications dynamically without modifying base notification classes.
- Relevance: Decorator pattern enables runtime feature addition. Common in middleware, filters, and feature toggles.
- Real-World: Java I/O streams, Python decorators, Express.js middleware use decorator pattern.
- Pattern: Decorator adds behavior to objects dynamically without altering structure.
Decorator attaches additional responsibilities to objects dynamically. Provides flexible alternative to subclassing for extending functionality.
Notification: Component interfaceBaseNotification: Concrete componentEncryptedNotification,CompressedNotification: Concrete decoratorsNotificationDecorator: Abstract decorator class
- Define
Notificationinterface withsend()method - Create
BaseNotificationimplementing core functionality - Create abstract
NotificationDecoratorwrappingNotification - Implement concrete decorators (Encrypted, Compressed, Retry)
- Allow decorator chaining for multiple features
- Decorators call wrapped object's method and add behavior
- Decorator ordering matters (encrypt then compress vs compress then encrypt)
- Performance overhead of multiple decorators
- Error handling in decorator chain
- Circular decorator references
Design a file system that can represent both files and directories uniformly. Directories can contain files and other directories. Support operations like calculateSize(), search(), delete() on both.
- Relevance: Composite pattern is fundamental for tree structures. Common in UI frameworks, file systems, organizational hierarchies.
- Real-World: Operating systems, IDEs, and UI frameworks use composite pattern extensively.
- Pattern: Composite composes objects into tree structures to represent part-whole hierarchies.
Composite lets you compose objects into tree structures. Clients treat individual objects and compositions uniformly.
FileSystemComponent: Component interfaceFile: Leaf componentDirectory: Composite component containing childrenFileSystem: Root of the tree structure
- Define
FileSystemComponentinterface with common operations Fileimplements interface directly (leaf)Directoryimplements interface and contains list ofFileSystemComponent- Directory operations delegate to children
- Support recursive operations (size calculation, search)
- Handle parent-child relationships
- Circular references (directory containing itself)
- Empty directories
- Permission checks on operations
- Large directory trees (performance)
Design a simplified interface for a complex microservices system. The gateway should provide unified endpoints that internally coordinate multiple services (Authentication, Payment, Inventory, Shipping).
- Relevance: Facade pattern simplifies complex subsystems. Essential in microservices architecture.
- Real-World: API Gateways (Kong, AWS API Gateway) provide unified interface to multiple backend services.
- Pattern: Facade provides simplified interface to complex subsystem.
Facade provides unified interface to set of interfaces in subsystem. Defines higher-level interface that makes subsystem easier to use.
APIGateway: Facade classAuthService,PaymentService,InventoryService: Subsystem classesOrderService: Orchestrates multiple servicesClient: Uses simplified facade interface
- Identify complex subsystem (multiple microservices)
- Create
APIGatewayfacade with simplified methods - Facade coordinates calls to multiple services
- Handle service failures and fallbacks
- Implement request/response transformation
- Add caching and rate limiting at facade level
- Service failures and circuit breakers
- Partial failures (some services succeed, others fail)
- Request timeout handling
- Service discovery and load balancing
Design a proxy for a database service that adds caching layer. The proxy should intercept database calls, check cache first, and only query database on cache miss.
- Relevance: Proxy pattern is fundamental for cross-cutting concerns. Common in caching, security, logging, lazy loading.
- Real-World: Hibernate lazy loading, Spring AOP, CDN proxies use proxy pattern.
- Pattern: Proxy provides placeholder for another object to control access.
Proxy provides surrogate or placeholder for another object to control access. Can add functionality like caching, security, lazy loading.
DatabaseService: Subject interfaceRealDatabaseService: Real subject (actual database)CachingProxy: Proxy implementing same interfaceCache: Storage for cached data
- Define
DatabaseServiceinterface - Implement
RealDatabaseServicewith actual database calls - Create
CachingProxyimplementing same interface - Proxy maintains reference to real service
- Intercept calls: check cache, return if found, else delegate to real service
- Implement cache invalidation strategies
- Cache expiration and TTL
- Cache invalidation on updates
- Memory management for cache
- Cache stampede (thundering herd)
Design a UI rendering system that can work with different rendering engines (Web, Mobile, Desktop) and different UI themes (Light, Dark). The system should allow adding new engines or themes independently.
- Relevance: Bridge pattern decouples abstraction from implementation. Common in cross-platform frameworks.
- Real-World: React Native, Flutter use bridge pattern to abstract platform differences.
- Pattern: Bridge separates abstraction from implementation so both can vary independently.
Bridge decouples abstraction from implementation so both can vary independently. Useful when you want to avoid permanent binding between abstraction and implementation.
UIComponent: Abstraction interfaceButton,TextField: Concrete abstractionsRenderingEngine: Implementation interfaceWebRenderer,MobileRenderer: Concrete implementationsTheme: Additional dimension (Light, Dark)
- Separate abstraction (UI components) from implementation (rendering)
- Define
RenderingEngineinterface - Create concrete renderers for each platform
- UI components contain reference to renderer
- Components delegate rendering to engine
- Support theme variations through composition
- Platform-specific limitations
- Theme switching at runtime
- Performance across platforms
- Accessibility features per platform
- Understand Relationships: Structural patterns are about relationships between objects
- Composition over Inheritance: Most structural patterns favor composition
- Interface Design: Focus on clean, minimal interfaces
- Performance: Consider overhead of additional layers
- Real-World Mapping: Relate patterns to libraries/frameworks you've used