Abstract factory
The object creation mode bypasses new to avoid the tight coupling caused by the object creation (new needs to rely on specific classes), so as to support the stability of object creation. It is the first step after abstracting the interface
motivation
It mainly solves a series of "interdependent objects". The Factory method is to solve "single object", that is, multiple factories form a general base class.
definition
Provide an interface to create a series of "related or interdependent objects" without specifying their specific classes.
Sample code
class EmployeeDAO { public: vector<Employee> GetEmployees() { SqlConnection* connection = new SqlConnection(); connection->ConnectionString = "..."; SqlCommand* command = new SqlCommand(); command->CommandText = "@@@"; command->SetConnection(connection); SqlDataReader* reader = command->ExecuteReader(); while(reader->Read()) { // ... } } };
Suppose we have an EmployeeDAO that can access the database and then obtain some employee information. The process of connecting to the database here is that Sqlxxx related classes depend on each other, and here they all depend on specific classes. Later, if the requirements change, such as using other databases, this class will not be applicable. Well, those who have learned about the factory pattern can know that now we need to add a layer of new abstraction to create specific classes. Here, we need to create a factory base class for each new class.
// connection factory base class class ConnectionFactory { public: virtual Connection* CreateConnection() = 0; virtual ~ConnectionFactory(){} }; // connection factory specific class class SqlConnectionFactory : public ConnectionFactory { public: virtual Connection* (){ return new SqlConnection(); } } // connection factory specific class class OracleConnectionFactory : public ConnectionFactory { public: virtual Connection* (){ return new OracleConnection(); } } // command factory base class class CommandFactory { public: virtual Command* CreateCommand() = 0; virtual ~CommandFactory(){} }; // command factory specific class class SqlCommandFactory : public CommandFactory { public: virtual Command* (){ return new SqlCommand(); } } // command factory specific class class OracleCommandFactory : public CommandFactory { public: virtual Command* (){ return new OracleCommand(); } } // dataReader factory base class class DataReaderFactory { public: virtual DataReader* CreateDataReader() = 0; virtual ~DataReaderFactory(){} }; // dataReader factory concrete class class SqlDataReaderFactory : public DataReaderFactory { public: virtual DataReader* (){ return new SqlDataReader(); } } // dataReader factory concrete class class OracleDataReaderFactory : public DataReaderFactory { public: virtual DataReader* (){ return new OracleDataReader(); } } class EmployeeDAO { ConnectionFactory* connectionFactory; // polymorphic CommandFactory* commandFactory; DataReaderFactory* dataReaderFactory; public: // The constructor for initializing the member variable of EmployeeDAO is omitted here vector<Employee> GetEmployees() { Connection* connection = connectionFactory->CreateConnection(); connection->ConnectionString = "..."; Command* command = commandFactory->CreateCommand(); command->CommandText = "@@@"; command->SetConnection(connection); // Relevance DataReader* reader = command->ExecuteReader(); // Relevance while(reader->Read()) { // ... } } };
The above implementation adopts the idea of factory mode, which does solve the problem of program fragility caused by creating object dependent concrete classes. However, there is another problem that the operations between databases need to be consistent. At present, three independent abstract factories are passed into the EmployeeDAO class as parameters, but the current structure can not ensure that they are consistent, It is entirely possible that the Sql connection is passed in, but the oracle command is passed in. This will definitely report an error. Therefore, the pattern of Abstract Factory will go a step further and put together the factory base classes that are related between related.
class IDBFactory { public: virtual Connection* CreateConnection() = 0; virtual Command* CreateCommand() = 0; virtual DataReader* CreateDataReader() = 0; virtual ~IDBFactory(){} }; class IDBSqlFactory : public IDBFactory{ public: virtual Connection* () { return new SqlConnection(); } virtual Command* () { return new SqlCommand(); } virtual DataReader* () { return new SqlDataReader(); } }; class IDBOracleFactory : public IDBFactory{ public: virtual Connection* () { return new OracleConnection(); } virtual Command* () { return new OracleCommand(); } virtual DataReader* () { return new OracleDataReader(); } }; class EmployeeDAO { IDBFactory* idbFactory; public: vector<Employee> GetEmployees() { Connection* connection = idbFactory->CreateConnection(); connection->ConnectionString = "..."; Command* command = idbFactory->CreateCommand(); command->CommandText = "@@@"; command->SetConnection(connection); // Relevance DataReader* reader = command->ExecuteReader(); // Relevance while(reader->Read()) { // ... } } };
So far, the above has completed the Abstract Factory pattern, which combines the interrelated factory interfaces to achieve high cohesion, polymorphism and loose coupling.
Structure diagram
summary
- If there is no need to deal with the demand change of "multi series object construction", it is not necessary to use the Abstract Factory pattern, and a simple factory is enough.
- ”"Series objects" means that objects in a specific series have interdependence or interaction relationship, and objects in different series cannot depend on each other (sql command s cannot depend on oracle connection)
- Abstract Factory is mainly used to deal with the demand changes of "new series". The disadvantage is that it is difficult to deal with the demand changes of "new objects" (adding functional interfaces on the basis of connection, command and datareader). The requirement of abstract base classes is to be stable.
Summary of other design modes:
[design pattern] - Introduction and classification of design patterns