Apply the design pattern in Java-factory Method

Source: Internet
Author: User

Basic Concepts

Factorymethod is a creation mode. It defines an interface for creating objects, but allows subclass to decide which class to instantiate. the factory method mode is used when a class cannot predict the type of object to be created or when a class needs to be specified by the subclass. to put it simply, the factory method can generate different instances according to different conditions. Of course, these different instances generally belong to the same type and share a common parent class. the factory method encapsulates the specific process of creating these instances, simplifies the application of the client, and improves the program scalability, this allows you to add new classes with minimal changes in the future. generally, we use factory method as a standard method for object creation. When we find that more flexibility is required, we start to consider converting to other creation modes.

Simple Analysis

Figure 1 shows the structure of the factory method mode. Some terms are provided here to facilitate the description:

  1. Product: the abstract class of the product to be created.
  2. Concreteproduct: a subclass of product, a series of specific products.
  3. Creator: Specifies the abstract Creator interface, which declares that the factory method of the product type object is returned.
  4. Concretecreator: Specifies the creator. Override the factory method in the Creator and return the concreteproduct type instance.

Figure 1: Factory method Schema
 

From this we can clearly see the parallel correspondence: Product <===> creator; conreteproduct <==> conretecreator

Abstract products correspond to abstract creators, and specific products correspond to specific creators. What are the benefits of doing so? Why don't we directly use specific products and specific creators to fulfill our requirements? We can also do this. however, in the factory method mode, the customer (client) only needs to reference the abstract product and creater. It does not care about the specific concreteproduct and concretecreator. In this way, we can gain additional benefits:

  • First, the client can obtain the generated instances from the abstract creator. The role of the Creator separates the client from the product creation process. The customer does not have to worry about returning the specific product, you don't have to worry about how these products are created. at the same time, concreteproduct is also hidden behind the product. conreteproduct inherits all the attributes of the product and implements the abstract methods defined in the product. According to the cast principle in Java, the concreteproduct generated by concretecreator can be automatically scaled to a product. in this way, the concreteproduct with different substantive content can be unified as the product in form and accessed through the Creator provided to the client.
  • Secondly, when we add a new concretecreator, because the interface provided by the Creator remains unchanged, the client program will not be changed at all, and will not cause a disaster that will take the whole body as soon as possible, this is the embodiment of good encapsulation. however, if you directly use the concreteproduct and concretecreator classes, you cannot do this in any way. the excellent object-oriented design encourages the use of encapsulation and delegation, while the factory method mode is a typical example of using encapsulation and delegation, here, the encapsulation is embodied by the abstract creator, and the delegate is to assign the responsibility for creating objects to the specific creator concretecreator.

Now, let's look back at some of the basic concepts. It may be difficult to understand at first. Is it clear that it has become much clearer now.

Next let's take a look at how to implement the factory method mode in Java to further deepen our understanding of it.

Implementation

First of all, using the factory method mode to create an object does not necessarily make our code shorter. Actually, it is often longer. We also use more classes, the real purpose is to flexibly create uncertain objects. in addition, the code reusability is improved, and the client application is simplified. The code of the client program is greatly reduced and more readable.

  1. Standard Implementation: Here I use Bruce Eckel to describe the typical shape of OO ideas. in this way, you will be familiar with it. I wrote the following DEMO code based on the structure defined in figure 1. this Code creates different shape instances. Each instance performs two operations: Draw and erase. the specific creation process is delegated to oshapefactory.

    1. A first defines an abstract class shape and two abstract methods.

    Abstract class shape {
    // Sketch shape
    Public abstract void draw ();
    // Erase the shape
    Public abstract void erase ();
    Public string name;
    Public shape (string aname ){
    Name = aname;
    }
    }

    1. B defines two subclasses of shape: circle and square to implement the abstract method defined in shape.

    // Circular subclass
    Class circle extends shape {
    Public void draw (){
    System. Out. println ("it will draw a circle .");
    }
    Public void erase (){
    System. Out. println ("It will erase a circle .");
    }
    // Constructor
    Public circle (string aname ){
    Super (aname );
    }
    }
    // Square subclass
    Class square extends shape {
    Public void draw (){
    System. Out. println ("it will draw a square .");
    }
    Public void erase (){
    System. Out. println ("It will erase a square .");
    }
    // Constructor
    Public Square (string aname ){
    Super (aname );
    }
    }

    1. c defines the abstract creator. anoperation calls factorymethod to create an object and performs a series of operations on the object.

    Abstract class shapefactory {
    Protected abstract shape factorymethod (string aname );
    // Define a series of shapes in anoperation
    Public void anoperation (string aname ){
    Shape S = factorymethod (aname );
    System. Out. println ("the current shape is:" + S. Name );
    S. Draw ();
    S. Erase ();
    }
    }

    1. d defines two specific creators circlefactory and squarefactory corresponding to circle and square to implement the methodfactory method of the parent class.

    // Define the circlefactory that returns the circle instance
    Class circlefactory extends shapefactory {
    // Reload the factorymethod method to return the circle object
    Protected shape factorymethod (string aname ){
    Return new circle (aname + "(created by circlefactory )");
    }
    }

    // Define the squarefactory that returns the square instance
    Class squarefactory extends shapefactory {
    // Reload the factorymethod method to return the square object
    Protected shape factorymethod (string aname ){
    Return New Square (aname + "(created by squarefactory )");
    }
    }

    1. E test class: Pay attention to the conciseness of the client program, and there is no ambiguous condition judgment statement, you don't need to worry about the details of concreteproduct and concretecreator (because here I use anoperation to encapsulate the two methods in the product, so I didn't even see the product shadow, of course, it is good to put the specific call of methods in the product into the customer program ).

    Class main {
    Public static void main (string [] ARGs ){
    Shapefactory sf1 = new squarefactory ();
    Shapefactory sf2 = new circlefactory ();
    Sf1.anoperation ("shape one ");
    Sf2.anoperation ("shape two ");
    }
    }

    The running result is as follows:

    The current shape is: shape one (created by squarefactory)

    It will draw a square.

    It will erase a square.

    The current shape is: Shape two (created by circlefactory)

    It will draw a circle.

    It will erase a circle.

  2. Parameterized Factory method: This method uses the specified parameter as a flag to create the corresponding instance. This is a common method. for example, borderfactory in jfc is a good example. the following example uses a string as a flag for determination. If the parameter types are different, you can use the overload function to solve this problem, define a series of functions with the same name as the method body. Here Java. util. calendar. getinstance () is an excellent example. the parametric creation method overcomes one of the most significant defects in the factory method mode, that is, when there are many products, we have to create a series of specific constructors. however, on the client side, we must specify parameters to determine which class to create.

    2. A. We modify it based on the first method. First, we define an exception. In this way, when an incorrect parameter is input, we can get a more obvious error message.

    Class nothisshape extends exception {
    Public nothisshape (string aname ){
    Super (aname );
    }
    }

    2. B removed the two sub-classes of shapefactory and changed it to shapefactory, which is directly responsible for instance creation. shapefactory itself becomes a specific generator, and factorymethod is directly implemented using parameterized methods to return multiple objects.

    Abstract class shapefactory {
    Private Static Shape S;
    Private shapefactory (){}

    Static Shape factorymethod (string aname, string Atype) throws nothisshape {
    If (Atype. compareto ("square") = 0)
    Return New Square (aname );
    Else if (Atype. compareto ("circle") = 0)
    Return new circle (aname );
    Else throw new nothisshape (Atype );
    }

    // Define a series of shapes in anoperation
    Static void anoperation (string aname, string Atype) throws nothisshape {
    S = factorymethod (aname, Atype );
    System. Out. println ("the current shape is:" + S. Name );
    S. Draw ();
    S. Erase ();
    }
    }

    2. c test class: the client must specify a parameter to determine which class to create. In this example, anoperation is a static function and can be directly referenced.

    Class main {
    Public static void main (string [] ARGs) throws nothisshape {
    Shapefactory. anoperation ("shape one", "circle ");
    Shapefactory. anoperation ("shape two", "square ");
    Shapefactory. anoperation ("shape three", "Delta ");
    }
    }

    The running result is as follows:

    The current shape is: shape one
    It will draw a circle.
    It will erase a circle.
    The current shape is: Shape two
    It will draw a square.
    It will erase a square.
    Exception in thread "Main" nothisshape: Delta
    At shapefactory. factorymethod (shapefactory. Java: 10)
    At shapefactory. anoperation (shapefactory. Java: 15)
    At Main. Main (main. Java: 5)

  3. Dynamic loaders:

    Sometimes we will pass the concreteproduct instance to the Creator as a parameter. In this case, if you complete the creation process in the Creator, you must determine the specific type of the parameter (using instanceof ), then, the corresponding instance can be generated. A better way is to use the dynamic loader of Java to complete the process. for example:

    We get a shape subclass S, but we don't know the specific subclass, we can use the class's built-in method newinstance () to get the instance.

    Return (SHAPE) S. getclass (). newinstance ();

    If you are interested in this method, you can try it on your own. Due to the limited space, you will not write the specific code.

    After that:

    After reading this article, I believe that you have a clear understanding of the factory method mode. what I want to say is that we should not only care about the role of a specific model, but also understand its nature through phenomena. we need to learn models to deepen our understanding of object-oriented ideas, so that our understanding can be sublimated. the factory method mode seems simple, but it is actually profound. abstract, encapsulation, inheritance, delegation, polymorphism, interface programming, and other object-oriented concepts are all embodied here. only by grasping its essence can we use the mode flexibly, instead of using the mode for use.

    References

    • Thinking in pattern with Java ---- Bruce Eckel

    • The factory method design pattern by Gopalan Suresh Raj ---- http://gsraj.tripod.com/design/creational/factory/factory.html
    • Seng609_40 factory patterns paper ---- http://sern.ucalgary.ca /~ Kjfu/courses/seng60904/paper.html
    • Factory method Pattern ---- http: // www.ugolandini.net/factorymethodpattern.html
    • Design Patterns in Java ---- Bob Tarr
    • Design Patterns ---- Gang of Four
    • Dynamic class loading in Java ---- http: // www.pramodx.20m.com/dynamic_class_loading_in_java.htm

    About the author

     

    Liu Yu, a bachelor of information and computing science from Wuhan University, is familiar with Java language and J2EE ideas. He is a moderator of multiple Java forums in China and is now dedicated to ecrm kit development on the J2EE platform. You can contact him via jeru@163.net!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.