On the factory mode of GOF design mode

The essence of factory model

It realizes the separation of creator and caller
The core soul of design pattern is to clarify the division of labor
1. Instantiate the object and replace new with factory method
2. Press the key to select the implementation class and create object management and control. This decouples the caller from our implementation class

Classification of plant patterns

1. Simple factory mode:
It is used to produce any product in the same hierarchical structure (same parent class). (for new products, the existing code needs to be modified)
2. Factory method mode:
It is used to produce fixed products in the same hierarchical structure. (any product can be added)
3. Abstract factory mode:
Used to produce all products in different product families. (there is nothing we can do to add new products. We support adding product families)

Basic principles of dependence

OCP (opening and closing principle): a software entity is open to expansion and closed to modification;
Dip (dependency leading principle): program the interface, not the implementation (the implementation class implements the interface)
LOD: as for direct communication with friends, avoid communication with strangers;
That is, only with the input and output parameter classes of member variables or methods The public or protected methods provided in interact, and the internal ones are responsible for processing, no matter how complex

Simple factory

main points:

-Simple factory is also called static factory mode, that is, factory classes generally use static methods to return different object instances by accepting different parameters
-There is nothing we can do about the newly added products. We can't add new products without modifying the code

code:

Product block

/**
 * Product parent class of simple factory (common parent class of all products or abstract class)
 */
public interface Car {
	void run();
}

/**
 * Audi specific products
 */
public class Audi implements Car {

	@Override
	public void run() {
		System.out.println("Audi, run again!");
	}

}

/**
 * BYD specific products
 */
public class Byd implements Car {

	@Override
	public void run() {
		System.out.println("BYD, run again!");
	}

}

Simple factory classes are also called static factory classes

//Product Factory
public class CarFactory {
	
	public static  Car createCar(String type){
		if("audi".equals(type)){
			return new Audi();
		}else if("BYD".equals(type)){
			return new Byd();
		}else{
			return null;
		}
	}
}

Call class

/**
 * Simple factory case
 * @author Shang Xuetang Gao Qi www.sxt.com cn
 *
 */
public class Client02 {   //caller 
	//Get different product objects by passing different product types
	public static void main(String[] args) {
		Car c1 =CarFactory.createCar("audi");
		Car c2 = CarFactory.createCar("BYD");
		c1.run();
		c2.run();
	}
}

There is nothing you can do to modify the new product code

Factory method model

main points:

1. In order to avoid the shortcomings of simple factory mode, incomplete OCP (opening and closing principle)
2. The biggest difference between the factory method mode and the simple factory mode is that the simple factory mode has only one factory class (for a project or independent template), while the factory method mode has a group of factory classes that implement the same interface

Product code block

/**
 * Product parent class of factory method (common parent class of all products or abstract class)
 */
public interface Car {
	void run();
}

/**
 * Audi specific products
 */
public class Audi implements Car {

	@Override
	public void run() {
		System.out.println("Audi, run again!");
	}

}

/**
 * BYD specific products
 */
public class Byd implements Car {

	@Override
	public void run() {
		System.out.println("BYD, run again!");
	}

}

/**
 * Benz Specific products
 */
public class Benz implements Car {

	@Override
	public void run() {
		System.out.println("Run again!");
	}

}

Factory block

/**
 * Parent of all factory classes (also can be abstract classes)
 */
public interface CarFactory {
	 Car createCar();
}

/**
 * Specific factory class Byd
 */
public class BydFactory implements CarFactory {

	@Override
	public /**static*/ Car createCar() {
		return new Byd();
	}

}

/**
 * Specific factory class Benz
 */
public class BenzFactory implements CarFactory {

	@Override
	public /**static*/ Car createCar() {
		return new Benz();
	}

}

/**
 * Factory specific Audi
 */
public class AudiFactory implements CarFactory {

	@Override
	public /**static*/ Car createCar() {
		return new Audi();
	}

}

caller

/**
 * Obtain different product object instances according to different factory classes
 */
public class Client {
	public static void main(String[] args) {
		Car c1 = new AudiFactory().createCar();
		Car c2 = new BydFactory().createCar();
		Car c3 = new BenzFactory().createCar();

//		Create object instances using static methods
//		Car c1 = AudiFactory.createCar();
//		Car c2 = BydFactory.createCar();
//		Car c3 = nBenzFactory.createCar();

		c1.run();
		c2.run();
		c3.run();
	}
}

Factory method variants – similar to abstract factory methods

Product block

/**
 * Public parent of the product
 */
public interface Car {
	void run();
}

/**
 *Specific product byd
 */
public class Byd implements Car {

	@Override
	public void run() {
		System.out.println("BYD, run again!");
	}

}

/**
 * Specific products byd2
 */
public class Byd2 implements Car {

	@Override
	public void run() {
		System.out.println("BYD 2 run again!");
	}

}

/**
 * Benz Specific products
 */
public class Benz implements Car {

	@Override
	public void run() {
		System.out.println("Run again!");
	}

}

/**
 * Benz2 Specific products
 */
public class Benz2 implements Car {

	@Override
	public void run() {
		System.out.println("Benz 2 run again!");
	}

}

/**
 * Product specific Audi
 */
public class Audi implements Car {

	@Override
	public void run() {
		System.out.println("Audi, run again!");
	}


/**
 * Specific products audi2
 */
public class Audi2 implements Car {

	@Override
	public void run() {
		System.out.println("Audi 2 run again!");
	}

}

Factory block

/**
 * Parent of all factory classes (also can be abstract classes)
 */
public abstract class CarFactory {
	public static Car createCar(String carType) {
		return null;
	}

	public abstract Car getCar(String carType);
}


/**
 * Specific factory class Byd
 */
public class BydFactory extends CarFactory {

	public static Car createCar(String carType) {
		if("1".equals(carType)) {
			return new Byd();
		}else{
			return new Byd2();
		}
	}

	@Override
	public Car getCar(String carType) {
		return createCar(carType);
	}
}

/**
 * Specific factory class Benz
 */
public class BenzFactory extends CarFactory {

	public static Car createCar(String carType) {
		if("1".equals(carType)){
			return new Benz();
		}else{
			return new Benz2();
		}

	}

	@Override
	public Car getCar(String carType) {
		return createCar(carType);
	}

}

/**
 * Factory specific Audi
 */
public class AudiFactory extends CarFactory {

	public static Car createCar(String carType){
		if("1".equals(carType)){
			return new Audi();
		}else{
			return new Audi2();
		}
	}

	@Override
	public Car getCar(String carType) {
		return createCar(carType);
	}
}

Scheduling block

public class Client {
    /**
     * Pass different parameters to generate different factory products
     * @param args
     */
    public static void main(String[] args) {
        String factoryType = "Audi";
        Car car1  = getFactory(factoryType).getCar("1");
        Car car2  = getFactory(factoryType).getCar("2");
        factoryType = "Benz";
        Car car3  = getFactory(factoryType).getCar("1");
        Car car4  = getFactory(factoryType).getCar("2");
        factoryType = "Byd";
        Car car5  = getFactory(factoryType).getCar("1");
        Car car6  = getFactory(factoryType).getCar("2");

        car1.run();
        car2.run();
        car3.run();
        car4.run();
        car5.run();
        car6.run();
    }

    public static CarFactory getFactory(String factoryType){
        CarFactory factory = null;
        if("Byd".equals(factoryType)){
            factory = new BydFactory();
        }else if("Benz".equals(factoryType)){
            factory = new BenzFactory();
        }else{
            factory = new AudiFactory();
        }
        return factory;
    }
}

Comparison between simple factory and factory method

1. Structural complexity
Simple factory vs factory method is simple in structure and requires only one factory class. The factory method is to add factory classes with the increase of product families. The number of factory classes will be more and more, which increases the structural complexity
2. Code complexity
Code complexity and structure complexity are a pair of contradictions. The simple factory mode is relatively simple in structure and complex in code. The factory class of simple factory mode needs to add and modify many methods and codes with the increase of product classes; In the factory method mode, each specific factory class only completes a single task, and the code is concise
3. Difficulty of client programming
The factory method pattern factory class introduces an interface to realize OCP (opening and closing principle), but the factory class needs to be instantiated at the caller, while the simple factory class is a static class, and the caller does not need to instantiate, which is undoubtedly an advantage
4. Difficulty in management and maintenance
The factory method mode fully meets OCP and has good expansibility, but simple factories also have good expansibility (just need to modify the factory code); The increase or modification of product classes in factory methods will lead to the emergence of a large number of factory classes (basically one product and one factory class)
If the modification of the product class leads to the modification of the factory class, the factory method will make it difficult to track and deliver. However, a simple factory only needs to modify one factory class
In fact, we usually use the simple factory model

Abstract factory pattern

1. It is used to produce all products of different product families (there is nothing to do with adding new products; it supports adding product families)
2. Abstract factory mode is an upgraded version of factory method mode. There are multiple business varieties. Business classification is to produce the required objects through abstract factory, which is a good solution

Products

/**
 * Products - Tyres
 */
public interface Tyre {
	void revolve();
}

class LuxuryTyre implements Tyre {

	@Override
	public void revolve() {
		System.out.println("Rotation does not wear!");
	}
	
}

class LowTyre implements Tyre {

	@Override
	public void revolve() {
		System.out.println("Rotating wear fast!");
	}
	
}

/**
 * Products - Chairs
 */
public interface Seat {
	void massage();
}

class LuxurySeat implements Seat {

	@Override
	public void massage() {
		System.out.println("Can massage automatically!");
	}
	
}
class LowSeat implements Seat {

	@Override
	public void massage() {
		System.out.println("No massage!");
	}
	
}


package com.bjsxt.factory.abstractFactory;

/**
 * Engine - engine products
 */
public interface Engine {
	void run();
	void start();
}


class LuxuryEngine implements Engine{

	@Override
	public void run() {
		System.out.println("Turn fast!");
	}

	@Override
	public void start() {
		System.out.println("Fast start!It can start and stop automatically!");
	}
	
}

class LowEngine implements Engine{
	
	@Override
	public void run() {
		System.out.println("Turn slowly!");
	}
	
	@Override
	public void start() {
		System.out.println("Slow start!");
	}
	
}

Abstract factory class – create multiple Abstract products

/**
 * Automobile Abstract Factory
 */
public interface CarFactory {

	Engine createEngine();
	Seat createSeat();
	Tyre createTyre();
}

public class LowCarFactory implements CarFactory {

	@Override
	public Engine createEngine() {
		return new LowEngine();
	}

	@Override
	public Seat createSeat() {
		return new LowSeat();
	}

	@Override
	public Tyre createTyre() {
		return new LowTyre();
	}


}


public class LuxuryCarFactory implements CarFactory {

	@Override
	public Engine createEngine() {
		return new LuxuryEngine();
	}

	@Override
	public Seat createSeat() {
		return new LuxurySeat();
	}

	@Override
	public Tyre createTyre() {
		return new LuxuryTyre();
	}


}

Scheduling class

public class Client {

	public static void main(String[] args) {
		CarFactory  factory = new LuxuryCarFactory();
		Engine e = factory.createEngine();
		e.run();
		e.start();
		Tyre t = factory.createTyre();
		t.revolve();
		Seat s = factory.createSeat();
		s.massage();

	}
}

Summarize the difference between abstract factory and factory method

1. Abstract factory is aimed at multiple abstract product classes (multiple product structure levels);
The factory method is aimed at a single abstract product class (single product structure level);
2. The abstract factory class can create a single specific product instance of each product group; (multiple specific product instances)
The factory method can create a single specific product instance;
3.

Key points of factory mode

Simple factory mode (static factory mode):
Although it does not conform to the design principle to some extent, it has the most practical application
Factory method mode:
Expand by adding new factory classes without modifying existing classes
Abstract factory class
Products can not be added, but product families can be added (it can be understood that the instance of a specific factory has been defined in the abstract class, so add a public product abstract class - adding a specific factory)

Application scenario of factory mode

1. getInstance() method in Calendar in JDK
2. Obtaining Connection object in JDBC

Connection con = null;
try{
    //Load the static code block by getting the bytecode object, so as to load the registered driver
    Class.forName(String driver);

    //Register the URL to get the connection to the database and get the connection object
    con = DriverManager.getConnection(uri, username, password);

    ...

    con.close();
}catch(Exception e){
    ...
}finally{
    ...
}

3. Create a Session using SessionFactory in Hibernate

  Session It is the basis of persistence layer operation, equivalent to JDBC Medium Connnection. 

           Configuration config=new Configuration().configure();  //Read the default hibernate cfg. XML file

           SessionFactory sessionFactory=config.buildSessionFactory();  //Create an instance of sessionFactory through config

           Session session=sessionFactory.openSession();       //Get session

After that, we can call Session Provided save,find,flush And other methods to complete the persistence operation:

4. Create management bean object in IOC container in spring

/*Method 1: get the bean by id*/
Student student = context.getBean(Student.class);
System.out.println(student.getName());

/*Mode 2: pass class file get bean*/
Student s = (Student)context.getBean("student") ;
System.out.println(s.getName());

Method 3: obtain through factory method bean
 Static factory method
 Method class

package com.cn.cmc.beans;

import java.util.HashMap;
import java.util.Map;

public class StaticStudentFactory {
    private static Map<String,Student> map ;
    static {
        map = new HashMap<String, Student>();
        map.put("Ye Qingyi", new Student(100001,"Ye Qingyi",'M',25)) ;
        map.put("Zhang San", new Student(100002,"Zhang San",'F',22)) ;
    }
    /*Obtain an instance of a bean through a static method*/
    static Student getBean(String name){
        return map.get(name) ;
    }
}

Configuration in xml:

Obtain the instance through the static factory method
Factory method: corresponds to the method name of obtaining bean s configured in the factory
Constructor Arg: the parameter passed in by the get bean method

<bean id="student1" class="com.cn.cmc.beans.StaticStudentFactory" factory-method="getBean">
    <constructor-arg value="Ye Qingyi"></constructor-arg>
</bean>

5. Create parser object with DocumentBuilderFactory during XML parsing

(1) javax. xml. DocumentBuilderFactory in parsers package is an abstract factory class, which cannot be instantiated directly, but this class provides a newInstance method, which will automatically create a factory object and return it according to the parser installed by default on the local platform.
(2) Call documentbuilderfactory The newinstance () method gets the factory that creates the DOM parser.
DocumentBuilderFactory doc=DocumentBuilderFactory.newInstance();
(3) Call the newDocumentBuilder method of the factory object to get the DOM parser object.
DocumentBuilder db=doc.newDocumentBuilder();
(4) Convert the XML document to be parsed into an input stream so that the DOM parser can parse it
InputStream is= new FileInputStream("test.xml");
(5) Call the parse() method of the DOM parser object to parse the XML Document and get the Document object representing the whole Document. You can use the DOM feature to operate the whole XML Document.
Document doc=dombuilder.parse(is);
(6) Get the root node of the XML document
Element root=doc.getDocumentElement();
(7) Get the child nodes of the node
NodeList users=root.getChildNodes();

     
     public XmlReader() {
         DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance();
         try {
             DocumentBuilder domBuilder = domfac.newDocumentBuilder();
             InputStream is = new FileInputStream(new File(
             "C:/Users/sony/Desktop/test.xml"));
             Document doc = domBuilder.parse(is);
             Element root = doc.getDocumentElement();
             NodeList users = root.getChildNodes();
             if (users != null) {
                 for (int i = 0; i < users.getLength(); i++) {
                 Node user = users.item(i);
                 // TEXT_NODE indicates that this node is a text node
                 // ELEMENT_NODE indicates that the node is an element node
                    if (user.getNodeType() == Node.ELEMENT_NODE) {
                     // (7) Gets the attribute value of the node
                     // String email = user.getAttributes()
                     // .getNamedItem("email").getNodeValue();
                     // System.out.println(email);
                     // Note that the attributes of a node are also its child nodes. Its node type is also node ELEMENT_ NODE
                     // (8) Round robin child node
                         for (Node node = user.getFirstChild(); node != null; node = node.getNextSibling()){
                             if (node.getNodeType() == Node.ELEMENT_NODE) {
                                if (node.getNodeName().equals("name")) {
                                 String name = node.getNodeValue();
                                 String name1 = node.getFirstChild()
                                 .getNodeValue();
                                 System.out.println("name==" + name);
                                 System.out.println("name1==" + name1);
                                 }
                             if (node.getNodeName().equals("price")) {
                                 String price = node.getFirstChild()
                                .getNodeValue();
                                 System.out.println(price);
                                 }
                             }
                         }
                     }
                 }
             }
             NodeList node = root.getElementsByTagName("string");
            if (node != null) {
                 for (int i = 0; i < node.getLength(); i++) {
                     Node str = node.item(i);
                     String s = str.getFirstChild().getNodeValue();
                     System.out.println(s);
                 }
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
    }
          public static void main(String[] args) {
         XmlReader xmlReader = new XmlReader();
     }
 }
<?xml version="1.0" encoding="GB2312" standalone="no"?> 
<users>
    <user email="www.baidu.com">
        <name>Zhang San</name>
        <age>18</age>
        <sex>male</sex> 
    </user>
    <user>
        <name>Li Si</name>
        <age>16</age>
        <sex>female</sex> 
    </user>
    <user>
        <name>Wang Er Ma Zi</name>
        <age>25</age>
        <sex>Unknown</sex> 
    </user>
</users>

6. newInstance() of Class object in reflection

Tags: Java Design Pattern

Posted by JoeZ on Wed, 18 May 2022 17:38:10 +0300