The introduction of

  • Let’s say we have a driver who needs to get to a certain city, so we give him a car
public class Demo {
    public static void main(String[] args) {
        Car car = newCar(); car.run(); }}public class Car {
    public void run(a){
        System.out.println("The car is running..."); }}Copy the code
  • What if we want to give the driver a car all the time? (single)
  • First of all, we can’t let the drivers pass by themselvesnewGenerate a car instead by callingCarClass to provide a vehicle.
public class Car {
    private static Car car = new Car();// Used to provide the outside world, always the same car

    private Car(a){};// Private constructors, which can no longer obtain objects of this class from new outside of the class, guarantee singletons

    public Car getInstance(a){
        return car;
    }

    public void run(a){
        System.out.println("The car is running..."); }}public static void main(String[] args) {
    Car car = Car.getInstance();
    car.run();
}
Copy the code

 

Simple factory

  • So let’s think about, what if we didn’t want to have cars, we wanted to be able to customize the vehicles, and customize the processes that produce the vehicles, what would we do?
  • Once the concept of cars to vehicles comes into being, polymorphism should come into mind. We can define oneMoveableThe interface is declared on the interfacerun()Method, all vehicle classes implement this interface.
  • For the customized production process, we can produce the corresponding vehicle through a factory.
public interface Moveable {
    void run(a);
}

public class Car implements Moveable{

    public Car(a){};// Private constructors, which can no longer obtain objects of this class from new outside of the class, guarantee singletons

    public void run(a){
        System.out.println("The car is running..."); }}public abstract class VehicleFactory {
    public abstract Moveable create(a);
}

public class CarFactory extends VehicleFactory {
    @Override
    public Moveable create(a) {
        return newCar(); }}//Test
public static void main(String[] args) {
    VehicleFactory factory = new CarFactory();
    Moveable m = factory.create();
    m.run();
}
Copy the code

 

The abstract factory

  • Let’s clear the picture of a simple factory from my mind and talk about another factory implementation.
  • Let’s assume that the driver at the beginning is not a normal driver, who needs a vehicle to get to a city, an AK47, and an apple in case he needs one.
  • So we need to give him a factory to make this range of products.
  • In order to improve scalability, we also hope that different factories can make different series of products. For example, factory A mentioned above makes cars, AK47 and Apple. And factory B makes airplanes, rocket launchers, and little steamed buns.
//test
public static void main(String[] args) {
    AbstractFactory factory = new Factory1();
    Vehiche v = factory.createVehiche();
    Weapon w = factory.createWeapon();
    Food f = factory.createFood();

    v.run();
    w.fire();
    f.eat();
}

public abstract class Vehiche {// The abstract class of vehicle
    public abstract void run(a);
}

public abstract class Weapon {// Abstract class of weapon
    public abstract void fire(a);
}

public abstract class Food {// Abstract classes of food
    public abstract void eat(a);
}

public class Car extends Vehiche{a specific means of transportation@Override
    public void run(a) {
        System.out.println("The car starts..."); }}public class AK47 extends Weapon {// A specific weapon
    @Override
    public void fire(a) {
        System.out.println("Dah dah dah..."); }}public class Apple extends Food{// A specific type of food
    @Override
    public void eat(a) {
        System.out.println("Munching on an apple..."); }}// Abstract factory
public abstract class AbstractFactory {
    public abstract Vehiche createVehiche(a);
    public abstract Weapon createWeapon(a);
    public abstract Food createFood(a);
}

// Abstract factory implementation 1
public class Factory1 extends AbstractFactory {
    @Override
    public Vehiche createVehiche(a) {
        return new Car();
    }

    @Override
    public Weapon createWeapon(a) {
        return new AK47();
    }

    @Override
    public Food createFood(a) {
        return newApple(); }}Copy the code

 

  • To sum up, what are the pros and cons of an abstract factory versus a simple factory?
  • Abstract factories can produce a range of products and easily replace a range of products, but adding a variety to the range can be cumbersome. For example, add one to the above seriesarmorAbstract class, then abstract factory and the corresponding implementation will have to change the source code.
  • Simple factories can flexibly produce products of one variety, but if there are more varieties produced, there will be the problem of factories flooding.
  • The advantages and disadvantages of the two complement each other, so is there a factory implementation that can accommodate the advantages of the two? See belowspringFactory implementation, which provides a solution.

 

Spring’s bean factory

  • So let’s think about the original case again, and we have oneMoveableThe interface, it hasrunMethod,CarThe car class implements this interface.
public static void main(String[] args) {
    Moveable m = new Car();
    m.run();
}

public interface Moveable {
    void run(a);
}

public class Car implements Moveable{
    @Override
    public void run(a) {
        System.out.println("The car moves forward..."); }}Copy the code
  • In Spring’s bean factory, new objects do not passnewKeyword, but through the configuration file.
  • The specific process is: first read the configuration file to obtain the classclassObject and then passclassObject to create concrete instance objects.
public static void main(String[] args) throws Exception {
    // Obtain the configuration file
    Properties props = new Properties();
    props.load(Test.class.getClassLoader().getResourceAsStream("spring.properties"));
    // Get the class configured in the configuration file
    String vehicheTypeName = props.getProperty("vehicheTypeName");
    // Reflect to generate the corresponding object
    Moveable m = (Moveable) Class.forName(vehicheTypeName).newInstance();
    m.run();
}

//spring.properties
vehicheTypeName=designPattern.factory.springFactory.Car
Copy the code

 

  • The above is rightspringIn the bean factory simulation, we use the real onespringTo generate aCarObject, compare.
public static void main(String[] args) throws Exception { BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml"); Vehiche v = (Vehiche)bf.getBean("v"); v.run(); } / / configuration file < bean id = "v" class = "designPattern. Factory. Car" > < / bean >Copy the code
  • There is no difference in usage between our simple factory and Spring’s bean factory. ReallyspringAs simple as that, let’s simulate Spring’s bean factory implementation.

 

Simulate the Spring factory implementation

Simulation of the IOC

  • It is said thatspringIs abeanContainer, the following code shows how it is generatedbeanAnd put thebeanPut into a container for the user to obtain.
  • The idea is simple:
  1. createBeanFactoryFactory interface, adding methodsgetBean().
  2. createBeanFactoryThe implementation of the classClassPathXmlApplicationContextThe implementation class will show the concrete implementation of IOC.
  3. ClassPathXmlApplicationContextThe need for acontainerThe container holds the created bean object, which is used hereHashMapThe implementation.
  4. inClassPathXmlApplicationContextConstructor of thespringThe configuration file used heredom4j. Read the configuration filebeantheclassProperty is created using reflectionbeanObject. And then takeidandbeanObjects askeyandvalueAdd to the container.
  5. When the factory is calledgetBean()Method is used to find the correspondingbeanAnd return.
public static void main(String[] args) throws Exception { BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml"); Vehiche v = (Vehiche) bf.getBean("v"); v.run(); } / / the BeanFactory implementation class public class ClassPathXmlApplicationContext implements the BeanFactory {private Map < String, Object> container = new HashMap<>(); // The container used to hold the bean object // reads the XML configuration file in the constructor, The bean objects are created and the public in the container ClassPathXmlApplicationContext (String propAddr) throws the Exception {SAXReader reader = new SAXReader(); File file = new File(this.getClass().getClassLoader().getResource(propAddr).toURI()); Document document = reader.read(file); Element root = document.getRootElement(); List<Element> childElements = root.elements(); for (Element child : childElements) { Object bean = Class.forName(child.attributeValue("class")).newInstance(); container.put(child.attributeValue("id"), bean); } } @Override public Object getBean(String beanId) { return container.containsKey(beanId) ? container.get(beanId) : null; }} public interface BeanFactory {Object getBean(String beanId); } / / XML configuration bean < bean id = "v" class = "designPattern. Factory. Car" > < / bean >Copy the code