Factory Pattern
The Factory pattern is a creational design pattern that provides an interface for creating objects without specifying their concrete classes. It delegates the responsibility of object instantiation to subclasses or specialized factory methods. This pattern promotes loose coupling and encapsulates the object creation logic, allowing flexibility in creating different types of objects based on certain conditions or parameters.
Examples:
trait Logger { fn log(&self, message: &str); } struct ConsoleLogger; struct FileLogger; impl Logger for ConsoleLogger { fn log(&self, message: &str) { println!("Logging to console: {}", message); } } impl Logger for FileLogger { fn log(&self, message: &str) { // Code for logging to a file println!("Logging to file: {}", message); } } enum LoggerType { Console, File, } struct LoggerFactory; impl LoggerFactory { fn create_logger(&self, logger_type: LoggerType) -> Box<dyn Logger> { match logger_type { LoggerType::Console => Box::new(ConsoleLogger), LoggerType::File => Box::new(FileLogger), } } } struct App { logger: Box<dyn Logger>, } impl App { fn new(logger: Box<dyn Logger>) -> Self { App { logger } } fn run(&self) { self.logger.log("Application started"); // Rest of the application logic } } fn main() { let factory = LoggerFactory; let logger_type = LoggerType::Console; let logger = factory.create_logger(logger_type); let app = App::new(logger); app.run(); }
For Testing and Mocking Purpose:
// The trait representing the collaborator dependency trait Collaborator { fn do_something(&self); } // The concrete implementation of the collaborator struct RealCollaborator; impl Collaborator for RealCollaborator { fn do_something(&self) { println!("RealCollaborator: Doing something real..."); // Actual implementation of the collaborator's behavior } } // The factory that creates instances of the collaborator struct CollaboratorFactory; impl CollaboratorFactory { fn create_collaborator(&self) -> Box<dyn Collaborator> { // In a real scenario, this method can create and return a real collaborator Box::new(RealCollaborator) } } // The client code that uses the collaborator struct Client { collaborator: Box<dyn Collaborator>, } impl Client { fn new(collaborator: Box<dyn Collaborator>) -> Self { Client { collaborator } } fn perform_action(&self) { // Do something using the collaborator self.collaborator.do_something(); } } // The test/mock implementation of the collaborator struct MockCollaborator; impl Collaborator for MockCollaborator { fn do_something(&self) { println!("MockCollaborator: Doing something mock..."); // Custom implementation for testing purposes } } // The test code that uses the mocked collaborator #[cfg(test)] mod tests { use super::*; #[test] fn test_client_with_mock_collaborator() { let factory = CollaboratorFactory; let mock_collaborator = Box::new(MockCollaborator); let client = Client::new(mock_collaborator); client.perform_action(); // Perform assertions on the client's behavior with the mock collaborator } } fn main() { let factory = CollaboratorFactory; let collaborator = factory.create_collaborator(); let client = Client::new(collaborator); client.perform_action(); }