use global_registry::{FactoryRegistry, Factory};
trait DatabaseService: Send + Sync {
fn connect(&self) -> String;
fn query(&self, sql: &str) -> String;
}
#[derive(Debug)]
struct PostgreSQLService {
connection_string: String,
}
impl PostgreSQLService {
fn new(host: &str, database: &str) -> Self {
Self {
connection_string: format!("postgresql://{}:5432/{}", host, database),
}
}
}
impl DatabaseService for PostgreSQLService {
fn connect(&self) -> String {
format!("Connected to PostgreSQL: {}", self.connection_string)
}
fn query(&self, sql: &str) -> String {
format!("PostgreSQL executing: {}", sql)
}
}
#[derive(Debug)]
struct MySQLService {
connection_string: String,
}
impl MySQLService {
fn new(host: &str, database: &str) -> Self {
Self {
connection_string: format!("mysql://{}:3306/{}", host, database),
}
}
}
impl DatabaseService for MySQLService {
fn connect(&self) -> String {
format!("Connected to MySQL: {}", self.connection_string)
}
fn query(&self, sql: &str) -> String {
format!("MySQL executing: {}", sql)
}
}
#[derive(Debug)]
struct SQLiteService {
file_path: String,
}
impl SQLiteService {
fn new(file_path: &str) -> Self {
Self {
file_path: file_path.to_string(),
}
}
}
impl DatabaseService for SQLiteService {
fn connect(&self) -> String {
format!("Connected to SQLite: {}", self.file_path)
}
fn query(&self, sql: &str) -> String {
format!("SQLite executing: {}", sql)
}
}
#[derive(Clone)]
struct DatabaseConfig {
db_type: String,
host: Option<String>,
database: String,
}
impl DatabaseConfig {
fn postgresql(host: &str, database: &str) -> Self {
Self {
db_type: "postgresql".to_string(),
host: Some(host.to_string()),
database: database.to_string(),
}
}
fn mysql(host: &str, database: &str) -> Self {
Self {
db_type: "mysql".to_string(),
host: Some(host.to_string()),
database: database.to_string(),
}
}
fn sqlite(file_path: &str) -> Self {
Self {
db_type: "sqlite".to_string(),
host: None,
database: file_path.to_string(),
}
}
}
struct ServiceFactory;
impl ServiceFactory {
fn setup_factories() {
let factory_registry = FactoryRegistry::global();
let pg_factory: Factory<Box<dyn DatabaseService>> = Box::new(|| {
Box::new(PostgreSQLService::new("localhost", "production"))
});
factory_registry.register_factory(pg_factory)
.expect("Failed to register PostgreSQL factory");
let mysql_factory: Factory<MySQLService> = Box::new(|| {
MySQLService::new("mysql-server", "app_data")
});
factory_registry.register_factory(mysql_factory)
.expect("Failed to register MySQL factory");
let sqlite_factory: Factory<SQLiteService> = Box::new(|| {
SQLiteService::new("/tmp/app.db")
});
factory_registry.register_factory(sqlite_factory)
.expect("Failed to register SQLite factory");
let config_factory: Factory<DatabaseConfig> = Box::new(|| {
DatabaseConfig::postgresql("prod-server", "main_db")
});
factory_registry.register_factory(config_factory)
.expect("Failed to register config factory");
}
fn create_database_service(db_type: &str) -> Option<Box<dyn DatabaseService>> {
let factory_registry = FactoryRegistry::global();
match db_type {
"postgresql" => {
factory_registry.create::<Box<dyn DatabaseService>>().ok()
}
"mysql" => {
factory_registry.create::<MySQLService>()
.map(|service| Box::new(service) as Box<dyn DatabaseService>)
.ok()
}
"sqlite" => {
factory_registry.create::<SQLiteService>()
.map(|service| Box::new(service) as Box<dyn DatabaseService>)
.ok()
}
_ => None,
}
}
}
struct Application;
impl Application {
fn run() {
println!("=== Factory Pattern Example ===\n");
ServiceFactory::setup_factories();
let databases = vec!["postgresql", "mysql", "sqlite"];
for db_type in databases {
println!("--- Testing {} ---", db_type.to_uppercase());
if let Some(service) = ServiceFactory::create_database_service(db_type) {
println!("{}", service.connect());
println!("{}", service.query("SELECT * FROM users"));
} else {
println!("Failed to create {} service", db_type);
}
println!();
}
let factory_registry = FactoryRegistry::global();
if let Ok(config) = factory_registry.create::<DatabaseConfig>() {
println!("Created config: {} database at {:?}",
config.db_type, config.host);
}
println!("Factory registry usage complete");
}
}
fn main() {
Application::run();
}