Factory Method Pattern
The factory method pattern is the creation pattern. It defines an interface for creating objects and lets subclasses decide which factory class to instantiate.
It provides an optimal way to create objects. In factory mode, we create objects without exposing the creation logic to the client, just by using a common interface to point to the newly created object.
role
1. Abstract Factory (Creator)
Is the core role of the factory method pattern, and the factory class of any object created in the pattern must implement this interface;
2. Concrete Creator
This is the concrete factory class that implements the abstract factory interface, contains application-specific logic, and is called by the application to create product objects;
3. Abstract Products
The base class of the objects created by the factory method pattern, which is the common parent or jointly owned interface of the product objects;
4. Concrete Products
This role implements the interface defined by the abstract product role.
The sample
Namespace FactoryMethod contains the Logger log base class and four specific log classes, namely TextLogger text log class, BinaryLogger binary log class, DatabaseLogger database log class, and CloudLogger cloud log class. It also contains a LoggerFactory factory base class, which in turn contains four corresponding factory implementation classes. This example attempts to illustrate the workings of the factory method pattern using a logger.
public abstract class Logger {
public abstract void Log(string message);
}
Copy the code
Abstract logging base class Logger.
public class TextLogger : Logger {
public override void Log(string message) {
Console.WriteLine($"INFO {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff")}" +
$" [{this.LoggerType()}] {message}"); }}Copy the code
Logs are recorded in text format.
public class BinaryLogger : Logger {
public override void Log(string message) {
Console.WriteLine($"INFO {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff")}" +
$" [{this.LoggerType()}] {message}"); }}Copy the code
Logs are recorded in binary format.
public class DatabaseLogger : Logger {
public override void Log(string message) {
Console.WriteLine($"INFO {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff")}" +
$" [{this.LoggerType()}] {message}"); }}Copy the code
Logs are recorded in the form of a database.
public class CloudLogger : Logger {
public override void Log(string message) {
Console.WriteLine($"INFO {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff")}" +
$" [{this.LoggerType()}] {message}"); }}Copy the code
Logs are recorded in the form of a cloud server.
public abstract class LoggerFactory {
public abstract Logger CreateLogger();
}
Copy the code
Factory base class for production loggers.
public class TextFactory : LoggerFactory {
public override Logger CreateLogger() {
return newTextLogger(); }}Copy the code
public class BinaryFactory : LoggerFactory {
public override Logger CreateLogger() {
return newBinaryLogger(); }}Copy the code
public class DatabaseFactory : LoggerFactory {
public override Logger CreateLogger() {
return newDatabaseLogger(); }}Copy the code
public class CloudFactory : LoggerFactory {
public override Logger CreateLogger() {
return newCloudLogger(); }}Copy the code
Four concrete factory classes to generate the appropriate logger.
public static class Extentions {
public static string LoggerType(this Logger logger) {
return logger
.ToString()
.Replace(nameof(FactoryMethod) + "."."")
.Replace(nameof(Logger), ""); }}Copy the code
Defines an extension for handling log strings.
public class Program {
private static LoggerFactory _factory = null;
private static Logger _logger = null;
public static void Main(string[] args) {
_factory = new TextFactory();
CreateLogger();
_factory = new BinaryFactory();
CreateLogger();
_factory = new DatabaseFactory();
CreateLogger();
_factory = new CloudFactory();
CreateLogger();
Console.ReadKey();
}
const string LOG_MESSAGE = "I logged a lot of {0} info!";
private static void CreateLogger() {
_logger = _factory.CreateLogger();
_logger.Log(string.Format(LOG_MESSAGE, _logger.LoggerType())); }}Copy the code
This is the caller’s code, which first needs to maintain the log and factory base classes, then create the different loggers and log the contents. Here is the output of this case:
INFO 201807 -- 20 06:17:02.871 [Text] I logged a lot of Text info!
INFO 201807 -- 20 06:17:02.928 [Binary] I logged a lot of Binary info!
INFO 201807 -- 20 06:17:02.932 [Database] I logged a lot of Database info!
INFO 201807 -- 20 06:17:02.933 [Cloud] I logged a lot of Cloud info!
Copy the code
advantages
A caller who wants to create an object needs only to know its name. 2, high scalability, if you want to add a product, just extend a factory class can; 3. Mask the concrete implementation of the product generation, and the caller only cares about the interface of the product.
disadvantages
1. Each time a product is added, a concrete class and object implementation factory need to be added, doubling the number of classes in the system, increasing the complexity of the system to a certain extent, but also increasing the dependence of concrete classes in the system; 2. Only one specific product can be created in a specific factory.
Usage scenarios
1. When a class does not know the class of the object it needs. 2. In the factory method mode, the client does not need to know the class name of the specific product class, but only the corresponding factory; 3. When a class wants to specify that its subclasses create objects.