Why?
The factory mode is our most commonly used model. The famous Jive forum has used the factory mode extensively. The factory mode can be seen everywhere in Java program systems.
Why is the factory model so commonly used? Because the factory mode is equivalent to creating the new instance object, we often need to generate instance objects according to Class, for example, A a = new A () Factory mode is also used to create instance objects, so in the future, there will be multiple eyes. Can you consider using the factory model? Although doing so may do more work, it will bring more scalability and as few modifications as possible to your system.
Let's take the Sample class as an example. If we want to create an instance object for the Sample:
Sample sample = new Sample ();
However, we usually perform vertex initialization when creating a sample instance, such as assigning values to query databases.
First, we can use the Sample constructor to generate an instance and write it as follows:
Sample sample = new Sample (parameter );
However, if Initialization is not as simple as assigning values when creating a sample instance, it may be a long piece of code. If it is also written to the constructor, then your code is ugly (Refactor reorganization is required ).
The reason is that the Code is ugly. Beginners may not feel this way. We will analyze the following. If the initialization work is a long piece of code, it means a lot of work to be done and a lot of work is loaded into a method, it is very dangerous to put a lot of eggs in one basket. This is also based on Java's object-oriented principle. The object-oriented Encapsulation (Encapsulation) and dispatch (Delegation) tell us that, assign long codes as much as possible to "cut" each segment, and then "encapsulate" each segment (reducing the coupling and association between segments). In this way, risks are dispersed, if you need to modify each segment in the future, nothing will happen again.
In this example, we need to separate the instance creation and use, that is, separate the large amount of initialization work required to create an instance from the constructor of the Sample.
In this case, we need the Factory mode to generate the object, and we cannot use the simple new Sample (parameter) above ). In addition, if the Sample has an inheritance such as MySample, We need to abstract the Sample into an interface according to the interface-oriented programming. sample is an interface with two subclasses: MySample and HisSample. we want to instantiate them as follows:
Sample mysample = new MySample ();
Sample hissample = new HisSample ();
As the project goes deeper, the Sample may "give birth to many sons", so we need to instantiate these sons one by one. Even worse, we may need to modify the previous Code: add an instance that later gave birth to a son. this is unavoidable in traditional programs.
But if you consciously use the factory model from the very beginning, these troubles will be gone.
Factory method
You will create a factory dedicated to producing Sample instances:
Public class Factory {
Public static Sample creator (int which ){
// GetClass generates samples. Generally, dynamic classes can be used to load the loaded classes.
If (which = 1)
Return new SampleA ();
Else if (which = 2)
Return new SampleB ();
}
}
In your program, if you want to instantiate the Sample, use
Sample sampleA = Factory. creator (1 );
In this way, the entire process does not involve the specific sub-classes of the Sample to achieve the encapsulation effect, which reduces the chance of Error modification. This principle can be expressed in a very popular way: the more specific things are done, the easier it is to set errors. each person who has done a specific job has a deep understanding. On the contrary, the higher the officer is, the more abstract the words are, the less likely the fan errors will be. it seems that we can understand the truth of life from the programming? Haha.
To use the factory method, pay attention to several roles. First, you must define the product interface. The Sample interface implementation class, such as SampleA, must be included in the product interface, used to generate the product Sample. For example, the rightmost is the production object Sample:
A little more complicated is to expand the factory class, and the factory class also inherits its concreteFactory implementation class.
Abstract Factory
Factory Methods Abstract Factory ).
The difference between the two modes lies in the complexity of creating objects. If the method for creating an object becomes complicated, for example, the factory method above creates an object Sample. If we still have a new product interface Sample2.
Assume that Sample has two concrete classes SampleA and SamleB, and Sample2 has two concrete classes Sample2A and SampleB2.
In this case, the Factory in the above example is converted into an abstract class, and the common part is encapsulated in the abstract class. Different parts are implemented using subclasses. below, the Factory in the above example is extended to an abstract Factory:
Public abstract class Factory {
Public abstract Sample creator ();
Public abstract Sample2 creator (String name );
}
Public class SimpleFactory extends Factory {
Public Sample creator (){
.........
Return new SampleA
}
Public Sample2 creator (String name ){
.........
Return new Sample2A
}
}
Public class BombFactory extends Factory {
Public Sample creator (){
......
Return new SampleB
}
Public Sample2 creator (String name ){
......
Return new Sample2B
}
}
We can see from the above that two factories each produce a set of Sample and Sample2. Maybe you may wonder, why can't I use two factory methods to produce Sample and Sample2 separately?
Another key point of the abstract factory is that there is a certain relationship between the methods for producing Sample and Sample2 in SimpleFactory, so we need to bind these two methods to a class, this factory class has its own characteristics, maybe the manufacturing process is unified, for example: the manufacturing process is relatively simple, so the name is SimpleFactory.
In practical applications, the factory method is used more often and combined with the dynamic class loader,
Example
Let's take Jive's ForumFactory as an example. This example is discussed in the previous Singleton mode. Now we will discuss its factory mode:
Public abstract class ForumFactory {
Private static Object initLock = new Object ();
Private static String className = "com. jivesoftware. forum. database. DbForumFactory ";
Private static ForumFactory factory = null;
Public static ForumFactory getInstance (Authorization authorization ){
// If no valid authorization passed in, return null.
If (authorization = null ){
Return null;
}
// Singleton single-State mode is used below
If (factory = null ){
Synchronized (initLock ){
If (factory = null ){
......
Try {
// Dynamic reprint class
Class c = Class. forName (className );
Factory = (ForumFactory) c. newInstance ();
}
Catch (Exception e ){
Return null;
}
}
}
}
// Now, return proxy. Used to restrict access to forum
Return new ForumFactoryProxy (authorization, factory,
Factory. getPermissions (authorization ));
}
// The method for creating forum is completed by inheriting the subclass of forumfactory.
Public abstract Forum createForum (String name, String description)
Throws UnauthorizedException, ForumAlreadyExistsException;
....
}
Because the current Jive stores Forum posts and other content data through the database system, if you want to change it to the file system, this factory method ForumFactory provides a dynamic interface:
Private static String className = "com. jivesoftware. forum. database. DbForumFactory ";
You can use the self-developed forum creation method to replace com. jivesoftware. forum. database. DbForumFactory.
In the above Code, three modes are used. Besides the factory mode, Singleton single-State mode and proxy mode are used to authorize users to access forum, because there are two types of users to access forum: one is to register a user and the other is a tourist guest, then the corresponding permissions are different, and this permission runs through the entire system, so a proxy is created, similar to the concept of gateway, this effect can be achieved very well.
Look at CatalogDAOFactory in the Java pet store:
Public class CatalogDAOFactory {
/**
* This method develops a special subclass to implement the DAO mode.
* The specific subclass definition is in the deployment descriptor of J2EE.
*/
Public static CatalogDAO getDAO () throws CatalogDAOSysException {
CatalogDAO catDao = null;
Try {
InitialContext ic = new InitialContext ();
// Dynamically Mount CATALOG_DAO_CLASS
// You can define your own CATALOG_DAO_CLASS so that you do not need to change too much code
// Complete the huge changes to the system.
String className = (String) ic. lookup (JNDINames. CATALOG_DAO_CLASS );
CatDao = (CatalogDAO) Class. forName (className). newInstance ();
} Catch (NamingException ne ){
Throw new CatalogDAOSysException ("
CatalogDAOFactory. getDAO: NamingException while
Getting DAO type: \ n "+ ne. getMessage ());
} Catch (Exception se ){
Throw new CatalogDAOSysException ("
CatalogDAOFactory. getDAO: Exception while getting
DAO type: \ n "+ se. getMessage ());
}
Return catDao;
}
}
CatalogDAOFactory is a typical factory method. catDao obtains the implementation subclass of CatalogDAOFactory through the dynamic classloader className. This implementation subclass is used to operate the catalog database in the Java pet store, you can customize your own implementation subclass based on different database types, and assign your subclass name to the CATALOG_DAO_CLASS variable.
It can be seen that the factory method indeed provides a very flexible and powerful dynamic expansion mechanism for the system structure. As long as we change the specific factory method, there is no need to change the system elsewhere, it is possible to change the system functions.
For how to apply the design pattern to a specific project, see Java Practical System Development Guide.