Design Pattern Application
Table of Contents
- Introduction
- Project Structure
- Core Components
- Architecture Overview
- Detailed Component Analysis
- Dependency Analysis
- Performance Considerations
- Troubleshooting Guide
- Conclusion
- Appendix
Introduction
This document systematically organizes the application and implementation practices of design patterns in the Sparrow framework, focusing on the following patterns and scenarios:
- Factory Pattern: Application in service creation and task scheduler instantiation
- Repository Pattern: Separation of abstraction and implementation in data access layer
- Observer Pattern: Publish/subscribe and asynchronous processing in event bus
- Strategy Pattern: Selection and switching of task execution strategies in hybrid scheduler
We will combine code path location, class diagrams and sequence diagrams to explain the problems solved by each pattern, the benefits brought, implementation details and extension methods, helping developers deeply understand and efficiently reuse.
Project Structure
Sparrow adopts an organization approach layered by domain and responsibility:
- bootstrap: Application bootstrap, container, configuration and startup process
- usecase: Use case layer interfaces and generic abstractions (repository, session, events, etc.)
- persistence/repo: Multiple persistence implementations (PostgreSQL, memory, Badger, etc.)
- eventbus: Event bus abstraction and memory implementation
- tasks: Task scheduling system (interface, concurrent/sequential/hybrid schedulers, wrapper)
- messaging: Message bus and stream processing (complementary to event bus)
- entity: Domain model base classes for aggregates, events, sessions, etc.
- logger, config, utils and other infrastructure modules
Core Components
- Container and Factory: Implements "constructor factory" through registration functions and reflection, supports anonymous/named dependency resolution and singleton caching
- Task Scheduler: Unified interface abstracts concurrent/sequential/hybrid three execution strategies, wrapper responsible for configuration and task building
- Event Bus: Publish/subscribe model, memory implementation supports asynchronous processing and timeout control
- Repository: Generic base class provides unified CRUD and query capabilities, concrete database implementations extend as needed
Architecture Overview
Sparrow's runtime is guided by App, injecting various subsystems (task scheduling, event bus, data access) through Container, and exposing task submission and strategy configuration capabilities uniformly through SchedulerWrapper.
Detailed Component Analysis
Factory Pattern: Service Creation and Task Scheduler Instantiation
Container Registration and Resolution:
- Register "constructor functions" through Register/RegisterNamed, use reflection to infer return type as key
- Resolve supports named/anonymous resolution, automatically injects dependencies and caches singleton instances
- Suitable for cross-module decoupling and test double replacement
Task Scheduler Factory:
- NewConcurrentScheduler/NewSequentialScheduler/NewHybridScheduler as concrete factories
- SchedulerWrapper.WithConcurrent/WithSequential provides configurable factory extension
Applicable Scenarios:
- Need to dynamically switch implementations based on environment/configuration (such as different databases, different event buses)
- Need to centrally manage lifecycle and dependency injection
Repository Pattern: Data Access Layer Abstraction
Abstraction Layer:
- BaseRepository[T] provides unified CRUD and query interfaces, constrains implementations to complete concrete database adaptation
Concrete Implementation:
- PostgresRepository[T] based on sqlx implementation, encapsulates transactions, batch operations, conditional queries, soft delete, etc.
Advantages:
- Decouples business use cases from data sources, convenient for replacing/extending storage backends
- Generic constraints on entity types, improves compile-time safety
Observer Pattern: Event Bus Publish/Subscribe
Memory Event Bus:
- Pub/Sub/Unsub/Close provides publish/subscribe/unsubscribe/close capabilities
- Asynchronously calls subscription handlers, built-in timeout control, avoids blocking publisher
Applicable Scenarios:
- Domain event decoupling, cross-module notification, observability metric collection
Strategy Pattern: Task Scheduling Strategy Selection
Strategy Interface:
- TaskScheduler abstracts unified scheduling behavior
Strategy Implementations:
- concurrentScheduler: Concurrent execution, supports maximum concurrency, TTL, retry and expiration cleanup
- sequentialScheduler: Sequential execution, strict serialization, suitable for scheduled/periodic tasks
- HybridScheduler: Chooses strategy based on task type and scheduling time, supports configuration mapping
Wrapper:
- SchedulerWrapper responsible for task building, retry strategy, concurrency and mode mapping configuration
Dependency Analysis
Container and Application
- App injects logging, routing, NATS connection, event publisher, session service, etc. through Container
- Supports named/anonymous resolution and singleton caching, reduces global state coupling
Scheduler Composition
- HybridScheduler composes concurrent/sequential schedulers, chooses strategy by task type and scheduling time
- SchedulerWrapper unified configuration entry, simplifies external calls
Event Bus and Task Scheduling
- Both event bus and task scheduler implement Start/Stop/Close interfaces, convenient for unified lifecycle management
Performance Considerations
Container Resolution
- Optimizes repeated resolution cost through singleton caching and named/anonymous resolution
Task Scheduling
- Concurrent scheduler uses polling + timeout control to avoid starvation; sequential scheduler reduces contention through queue and notification channels
- TTL and expiration cleanup prevent memory bloat
Event Bus
- Asynchronous processing and timeout control avoid blocking publisher; subscriber statistics facilitate capacity assessment
Troubleshooting Guide
Container Resolution Failure
- Symptom: Resolve returns "provider not found" or "output not pointer"
- Troubleshooting: Confirm Register/RegisterNamed constructor signature and return type match; ensure Resolve's out is non-null pointer
Task Scheduling Abnormal
- Symptom: Task status is failed/cancelled/dead letter
- Troubleshooting: View retry count and NextRetryAt; check task timeout and cancellation callback; verify scheduler mode configuration
Event Bus Blocking
- Symptom: Pub blocks or handler doesn't return for a long time
- Troubleshooting: Check handler timeout settings and implementation; confirm bus not closed; monitor subscriber count and processing duration
Conclusion
Sparrow achieves service decoupling, data access abstraction, event decoupling and flexible scheduling strategy switching through design patterns such as factory, repository, observer and strategy. Container and wrapper further reduce integration complexity, making extension and testing more convenient. It is recommended to follow existing interface and pattern conventions when adding new modules, prioritize using factory and wrapper for assembly, ensure system consistency and maintainability.
Appendix
Code Example Paths (for locating implementations)
Container Registration and Resolution:
Task Scheduler Interface and Implementations:
- TaskScheduler Interface
- Concurrent Scheduler
- Sequential Scheduler
- Hybrid Scheduler
- Scheduler Wrapper
Event Bus:
Repository:
Application Bootstrap and Assembly: