Overview
We know that the advantage of the simple factory model is to remove reliance on the client and the specific product, which is a violation of the "open-close principle"; The factory method pattern overcomes the drawbacks of the simple factory model, putting the product creation into a specific factory class, each of which is responsible for generating a product. But in practice, a factory class that only creates a single product is very rare, a general factory class will be responsible for creating a series of related products, if we want to design such a system, the factory method model can not meet the needs of the application, the abstract factory model introduced in this chapter to solve a series of product creation problems.
Defined
"Provides an interface to create a series of related or interdependent objects without specifying their specific classes. ”
The initial definition appears in the design pattern (addison-wesley,1994).
structure diagram
First, explain several roles of the above structure diagram:
Abstractfactory: Abstract factory interface, which should contain abstract methods for all product creation;
ConcreteFactory1 and ConcreteFactory2: A specific factory that creates product objects with a specific implementation;
Abstractproducta and ABSTRACTPRODUCTB: Abstract products, they may have a variety of different ways of implementation;
ProductA1, ProductA2, ProductB1 and ProductB2: Specific products, is the concrete realization of abstract products.
As you can see from the structure diagram, the greatest benefit of the abstract factory approach is the ability to easily transform the product family (such as id<abstractfactory> factory =[[ConcreteFactory1 alloc] init], You can create ProductA2 and ProductB2 only if you want to replace ConcreteFactory1 with ConcreteFactory2. In addition, the abstract factory method lets the concrete creation instance process detach from the client, the client is through their abstract interface operation instance, the product's concrete class name also is separated by the concrete factory implementation, does not appear in the customer code (for example Id<abstractproducta> product = [Factory Createproducta], the client simply does not know whether the specific class name is ProductA1 or ProductA2).
However, the abstract factory approach is also flawed, for example, now we want to add a new product, first of all, we need to add three classes: ABSTRACTPRODUCTC, ProductC1, ProductC2; We also need to change three classes: Abstractfactory, ConcreteFactory1, ConcreteFactory2, which is clearly against the "open-closed" principle. This is understandable, no one design model is perfect without blemish, this is like the world does not play undefeated martial Arts. What we can do is to isolate the change point as much as possible in the actual demand, to achieve the change, the least impact on the whole system, the change and the cost is the lowest.
Example
First, let's take a look at the class structure of database access.
OK, let's take a quick look at this class of structure diagram above, this diagram has three separate modules, one is the Ifactory interface, with different databases for the division principle of the Department to abstract, one is to access the different departments of the database, there is a database operation of the personnel are abstracted. The class diagram does not mention the next two classes that need to be shown, one is the user class, the other is the Department class, because these two classes are encapsulated in the database data, and the structure is not directly related, so did not show, here to explain, lest everyone cause confusion. In fact, calm down to look carefully, the structure is quite clear.
Oh, the following is still the same as the old, to show you the code.
Note: All of the code in this article is compiled in an arc environment.
User class Interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@interface User:nsobject
@property int *id;
@property NSString *name;
@end
User class implementation
Copy Code code as follows:
#import "User.h"
@implementation User
@synthesize Name =_name;
@synthesize ID =_id;
@end
Department class interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@interface Department:nsobject
@property int *id;
@property NSString *deptname;
@end
Department class implementation
Copy Code code as follows:
#import "Department.h"
@implementation Department
@synthesize ID =_id;
@synthesize Deptname =_deptname;
@end
Idepartment class Interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@class Department;
@interface Idepartment:nsobject
-(void) Insert: (department*) Department;
-(department*) getdepartment: (int) myId;
@end
Idepartment class implementation
Copy Code code as follows:
#import "IDepartment.h"
#import "Department.h"
@implementation Idepartment
-(void) Insert: (Department *) department{
Return
}
-(department*) getdepartment: (int) myid{
return nil;
}
@end
Sqlserverdepartment class Interface
Copy Code code as follows:
#import "IDepartment.h"
@interface Sqlserverdepartment:idepartment
@end
Sqlserverdepartment class implementation
Copy Code code as follows:
#import "SqlserverDepartment.h"
@implementation Sqlserverdepartment
-(void) Insert: (Department *) department{
NSLog (add a record to the department table in SQL Server);
}
-(department*) getdepartment: (int) myid{
NSLog (@ "Department table one record in SQL Server");
return nil;
}
@end
Accessdepartment class Interface
Copy Code code as follows:
#import "IDepartment.h"
@interface Accessdepartment:idepartment
@end
*accessdepartment class implementation
Copy Code code as follows:
#import "AccessDepartment.h"
@implementation Accessdepartment
-(void) Insert: (Department *) department{
NSLog (add a record to the department table in Access);
}
-(department*) getdepartment: (int) myid{
NSLog (@ "Get Department table a record in Access myID");
return nil;
}
@end
Iuser class Interface
Copy Code code as follows:
#import <Foundation/Foundation.h>
@class User;
@interfaceIUser: NSObject
-(void) Insert: (user*) User;
-(user*) GetUser: (int) MyID;
@end
Iuser class implementation
Copy Code code as follows:
#import "IUser.h"
#import "User.h"
@implementation Iuser
-(void) Insert: (User *) user{
Return
}
-(user*) GetUser: (int) myid{
return nil;
}
@end
Sqlserveruser class Interface
Copy Code code as follows:
#import "IUser.h"
@interface Sqlserveruser:iuser
@end
Sqlserveruser class implementation
#import "SqlServerUser.h"
@implementation Sqlserveruser
-(void) Insert: (User *) user{
NSLog (add a record to the user table in SQL Server);
}
-(user*) GetUser: (int) myid{
NSLog (@ "Get user table A record in SQL Server myID");
return nil;
}
@end
Accessuser class Interface
Copy Code code as follows:
#import "IUser.h"
@interface Accessuser:iuser
@end
Accessuser class implementation
Copy Code code as follows:
#import "AccessUser.h"
@implementation Accessuser
-(void) Insert: (User *) user{
NSLog (add a record to the user table in Access);
}
-(user*) GetUser: (int) myid{
NSLog (@ "Get a record of the user table in Access myID");
return nil;
}
@end
Ifactories class Interface
Copy Code code as follows:
#import "AccessUser.h"
@implementation Accessuser
-(void) Insert: (User *) user{
NSLog (add a record to the user table in Access);
}
-(user*) GetUser: (int) myid{
NSLog (@ "Get a record of the user table in Access myID");
return nil;
}
@end
Ifactories class implementation
Copy Code code as follows:
#import "IFactories.h"
#import "IUser.h"
#import "IDepartment.h"
@implementation Ifactories
-(iuser*) createuser{
return nil;
}
-(idepartment*) createdepartment{
return nil;
}
@end
Accessfactory class Interface
Copy Code code as follows:
#import "IFactories.h"
@interface accessfactory:ifactories
@end
Accessfactory class implementation
Copy Code code as follows:
#import "AccessFactory.h"
#import "AccessUser.h"
#import "AccessDepartment.h"
@implementation Accessfactory
-(iuser*) createuser{
return [[Accessuser alloc]init];
}
-(idepartment*) createdepartment{
return [[Accessdepartment alloc]init];
}
@end
Sqlserverfactory class Interface
Copy Code code as follows:
#import "IFactories.h"
@interface sqlserverfactory:ifactories
@end
Sqlserverfactory class implementation
Copy Code code as follows:
#import "SqlServerFactory.h"
#import "SqlServerUser.h"
#import "SqlserverDepartment.h"
@implementation Sqlserverfactory
-(iuser*) createuser{
return [[Sqlserveruser alloc]init];
}
-(idepartment*) createdepartment{
return [[Sqlserverdepartment alloc]init];
}
@end
Main method call
Copy Code code as follows:
#import <Foundation/Foundation.h>
#import "User.h"
#import "Department.h"
#import "IFactories.h"
#import "AccessFactory.h"
#import "IUser.h"
#import "IDepartment.h"
int main (int argc,const char * argv[])
{
@autoreleasepool {
User *user = [[user Alloc]init];
Department *dept = [[Department alloc]init];
Ifactories *factories = [[Accessfactory alloc]init];
Iuser *iu = [factories CreateUser];
[IU Insert:user];
[IU getuser:1];
Idepartment *myid = [factories createdepartment];
[MyId insert:dept];
[MyId getdepartment:1];
}
return 0;
}
Listed above a bunch of code, in fact, the purpose of listing these codes is only one, is to help like me as a basic not too good students to get started as soon as possible, have a perceptual understanding, the first hurdle.