First, Introduction
In object-oriented programming, the creation of objects is the most basic and most commonly used operations, reasonable object creation method to improve the reusability of code and reduce the coupling between modules is extremely important, and the factory model is specifically for the rational creation of the object is proposed. In the 23 common design patterns summarized by GOF, there are 3 factory models, namely, simple factory, factory method and abstract factory, this article will combine the simple example of the knot with the object-oriented programming, simple Factory mode and factory method model in detail, and give the complete code example, as for the abstract factory method, I'll cover it in more detail in a follow-up blog.
With the help of object-oriented programming, we encapsulate the different functional modules of a whole thing into one class, like a product with a specific function, and the instantiation of the class is the creation of the object as if it were the production process of the product. In object-oriented programming, all things and operations are objects, which of course includes the creation of objects, so we can encapsulate the creation of objects as a specialized class, and since the products are produced from the factory, we call this class the factory class. The design pattern used to create objects is also known as Factory mode.
second, simple Factory mode
2.1 Introductionconsidering a simple calculator application that requires the program to perform dependent operations on the input operators and operands and output the results, we first look at how a process-oriented programming idea is implemented.
Import Java.util.scanner;public class Progresscalculator {public static void main (string[] args) {Scanner scan NER = new Scanner (system.in); Used to get the input character System.out.print ("Please enter operand: a ="); int a = Integer.parseint (Scanner.nextline ()); Enter operand a System.out.print ("Please enter operand: b ="); int b = Integer.parseint (Scanner.nextline ()); Enter the operand b System.out.print ("Please enter the calculated symbol (' + ', '-', ' * ', '/'):"); String oprator = Scanner.nextline (); The input operator//judgment belongs to the operator and evaluates the result System.out.print ("calculated result:"); Switch (oprator) {case "+": System.out.println ("a + b =" + (A + b)); Break Case "-": System.out.println ("A-B =" + (a)); Break Case "*": System.out.println ("A * b =" + (A * b)); Break Case "/": if (b = = 0) {System.out.println ("divisor cannot be 0!") "); Break }//if System.out.println ("A/b =" + (A/b)); Break DEFAULT:SYSTEM.OUT.PRINTLN ("operator input error!) "); Break }//switch_oprator scanner.close (); }//main}/*progresscalculator*/
2.2 Analysis and implementationAlthough the above code implements the functionality required by the customer, if the customer wants to add two numbers to divide the remainder, we need to make a lot of modifications to the client code, so that although we add only one function, we let the earlier implemented subtraction operation be compiled again. This is nothing to this example, but in some large systems, recompiling all the code will be a huge job. In addition, in addition to the calculator, mobile phones, computers or tablets to use the arithmetic function, if you want to re-use the above code can only be achieved by means of copy and paste, in large-scale system is also not desirable. At this point, we need to use object-oriented methods to abstract and encapsulate the requirements, so as to solve the above problems. first of all, since all operations require operands and return operation results, we can abstract a basic operation class from the subtraction operation.
/** * The subtraction operation is abstracted into an operation class, with two operands and a method of returning the result of the operation, all the operator subclasses are inherited from the class, which can be used to implement the same parent class reference variable to achieve different sub-class operations. */abstract class Calculate {public int num_a; public int num_b; Abstract public int getresult ();} /*calculate*/
To be able to say, four kinds of operations should be independent of each other, according to a single functional principle, we encapsulate these four operations as four classes, they inherit from the basic Operation class and rewrite the GetResult () method to achieve their own unique functionality.
Addition operation Subclass Class Calculateadd extends Calculate { @Override public int GetResult () { return (num_a + num_b);
}//getresult}/*calculateadd*///Subtraction Operation Subclass Class Calculateminus extends Calculate { @Override public int GetResult () { return (num_a-num_b); } getresult}/*calculateminus*///Multiply operation Subclass class Calculatemutiple extends Calculate { @Override public int GetResult () { return num_a * num_b; } getresult}/*calculatemutiple*///Division operation Subclass Class Calculatedivision extends Calculate { @Override public int GetResult () { if (Num_b = = 0) try { throw new Exception ("divisor cannot be 0! "); } catch (Exception e) { e.printstacktrace (); } Try return num_a/num_b; } getresult}/*calculatedivision*/
To manage the creation of individual subclass objects, we define a factory class with a method that produces different objects based on the input parameters and returns the created object to a reference of the type of the parent class (the base Operation Class).
/** * Factory class, all sub-class objects are defined and returned by this class, like a factory specializing in the production of objects, which is called the factory class, if * to the system to delete the module, only need to modify the class, other modules are not affected. */class calculatefactory {public static Calculate createcalculate (String opt) throws Exception { switch (opt) { C2/>case "+": return new Calculateadd (); Case "-": return new Calculateminus (); Case "*": return new Calculatemutiple (); Case "/": return new Calculatedivision (); Default: throw new Exception ("operator input is incorrect!) "); } Switch }//createcalculate}/*objectfactory*/
In the client, the user does not need to understand the various operations of the specific implementation process, the child needs to create an instance of each specific operation class through a factory class, and the use of polymorphic characteristics through a reference variable of a basic operation class to invoke the function of each specific operation class, thereby isolating the user and the specific implementation of the function, reducing the coupling.
/** * Object-oriented thought implementation of the calculator code */public class Simplefactorydemo {public static void Main (string[] args) throws Exception { Scanner sc = new Scanner (system.in); Calculate calculator = null; System.out.print ("Please enter the calculation symbol (' + ', '-', ' * ', '/'):"); Calculator = Calculatefactory.createcalculate (Sc.nextline ()); The corresponding subclass is produced according to the type of calculation entered System.out.print ("Please enter operand: a ="); Calculator.num_a = Integer.parseint (Sc.nextline ()); System.out.print ("Please enter operand: b ="); Calculator.num_b = Integer.parseint (Sc.nextline ()); SYSTEM.OUT.PRINTLN ("Result:" + calculator.getresult ()); Sc.close (); } main}//Simplefactorydemo
2.3 BarsAt this point, we have completed the simple factory model of learning, in the simple factory model, the system of sub-module objects are generated through the factory class, there is a factory class can produce a variety of submodule objects of the static method, the static method has an input parameter, used to determine the end of the subclass to produce the object instance, The static method returns the parent class reference of the type for all child class pairs. The user only needs to know what features to use, and the conditions to produce these functional module objects, when used, the child class object is obtained by passing production conditions to the factory class, and the overriding method of each subclass is called through the polymorphic attribute of the ultimate parent class. UML diagram for simple Factory mode.
Figure-1 Simple Factory mode UML diagramThree, factory method mode
3.1 Introduction of the Simple factory model in the factory class need to determine the conditions of a given way to create objects, users only need to understand the ultimate parent of a feature and a factory class to obtain a variety of functions, more convenient, but after the use of simple Factory mode, if you need to add new features, then not only the addition of new functional subclasses, It is also necessary to change the switch branch statement in the factory class, which violates the open-closed principle, which simply means that the new class can be added, but the existing classes cannot be modified, so the factory method pattern is proposed.
3.2 Analysis and implementation in a simple factory model, a factory is responsible for producing all the objects, but in the factory method pattern, each class of objects is produced (created) by its own specialized factory, so there are several classes of the system, there are several factories, in order to improve the portability and reusability of code, We abstracted from these factory classes, in addition to a factory interface, defines the basic functions that all factory classes must have.
also use the example of the above calculator to illustrate the factory method pattern, because there are subtraction four specific operation classes, according to the definition of the factory method pattern, we need to define a factory class for each operation class, to create the corresponding instance of the Operation class specifically, To improve the reusability and extensibility of the code, we abstracted these factory classes once, creating a factory interface that defines the functions (methods) that a particular factory class should have.
Factory interface and Entity factory class for each operation subclass interface Instancefactory {public Calculate creatinstance ();} /*instancefactory*///addition factory class Addfactory implements Instancefactory { @Override public Calculate Creatinstance () { return new Calculateadd (); } creatinstance}/*addfactory*///Subtraction Factory class Minusfactory implements Instancefactory { @Override public Calculate creatinstance () { return new Calculateminus (); } creatinstance}/*minusfactory*///Multiplication Factory class Multiplefactory implements Instancefactory { @Override public Calculate creatinstance () { return new calculatemutiple (); } creatinstance}/*multiplefactory*///Division factory class Divisionfactory implements Instancefactory { @Override Public Calculate creatinstance () { return new calculatedivision (); } creatinstance}/*divisionfactory*/
In the client code, we create the appropriate factory instance of the required class and use the factory instance to create an instance of the required class.
Import Java.util.scanner;public class Factorymethoddemo {public static void main (string[] args) {Scanner Scann ER = new Scanner (system.in); Used to get the input character Calculate calculator = null; Operationfactory factory = null; System.out.print ("Please enter the calculation symbol (' + ', '-', ' * ', '/'):"); String oprator = Scanner.nextline (); The input operator//determines the factory switch (oprator) {case "+") that belongs to the operator and creates the corresponding class: Factory = new Addfactory (); Brea K Case "-": Factory = new Minusfactory (); Break Case "*": Factory = new Multiplefactory (); Break Case "/": if (b = = 0) {System.out.println ("divisor cannot be 0!") "); Break }//If factory = new Divisionfactory (); Break DEFAULT:SYSTEM.OUT.PRINTLN ("operator input error!) "); Break }//switch_opratorcalculator = Factory.creatinstance (); System.out.print ("Please enter operand: a ="); Calculator.num_a = Integer.parseint (scanner.Nextline ()); Enter operand a System.out.print ("Please enter operand: b ="); Calculator.num_b = Integer.parseint (Scanner.nextline ()); Enter the operand b System.out.println ("result is" + calculator.getresult ()); Scanner.close (); }//main}/*factorymethoddemo*/
2.3 BarsThe factory method pattern differs from the simple factory model in that the factory method pattern refines The factory class, creates a factory class for each sub-function class, and then abstracts a factory interface from each sub-function factory class to create a sub-function class object for the client landscape. This method further encapsulates the creation of the sub-function class object and avoids the need to fix the defect of the simple factory class when adding or removing the sub-functional class, and maintains the open-close principle, which is the UML diagram of the factory method pattern.
Figure-2 factory method mode UML diagram
Summary
there is only one factory in the simple factory model that is responsible for producing object instances of all classes, and the user simply needs to understand that a factory class and a parent class of all functions (the basic operations class in this example) can create and invoke unique methods for all functional subclasses, but if you want to add new functionality, It is necessary to modify the factory class to create a new instance of the functional subclass, which violates the open-closed principle; The factory method pattern ends this problem by defining a dedicated factory for each functional subclass, but if you want to add new functionality in Factory mode, you need to add new factory classes in addition to the classes that add new functionality. Adds complexity, and the factory method pattern puts the branch statements back into the client code, and it needs to modify the branch structure in the client to determine which class of factory to create. In the following blog post we will learn that this shortcoming can be solved by the reflection mechanism of Java, eliminate the overall code of the branch structure of the judgment, the reader can temporarily do not care.
all of the complete code used in this article is then uploaded to GitHub and the link is uploaded later.
Java design pattern (i) design pattern--Simple factory and factory method mode