Объяснение фабричного шаблона, введение в Spring IOC

Шаблоны проектирования

представлять

  • Предположим, есть водитель, которому нужно ехать в определенный город, поэтому мы даем ему машину
public class Demo {
    public static void main(String[] args) {
        Car car = new Car();
        car.run();
    }
}

public class Car {
    public void run(){
        System.out.println("汽车正在向前跑...");
    }
}
  • Что, если мы хотим всегда давать этому водителю машину? (Синглтон)
  • Во-первых, мы не можем пропустить водителя одногоnewпроизводит автомобиль, но вместо этого следует вызвать, позвонивCarМетод в классе предоставляет автомобиль внешнему миру.
public class Car {
    private static Car car = new Car();//用于提供给外界, 始终是同一辆车

    private Car(){};//私有构造方法, 在类之外不能通过new获得本类对象了, 保证了单例

    public Car getInstance(){
        return car;
    }

    public void run(){
        System.out.println("汽车正在向前跑...");
    }
}

public static void main(String[] args) {
    Car car = Car.getInstance();
    car.run();
}

 

простая фабрика

  • Рассмотрим следующее: если мы не хотим иметь только транспортное средство как транспортное средство, мы хотим настроить транспортное средство и настроить процесс производства транспортного средства, что нам делать?
  • Полиморфизм должен прийти на ум, как только возникнет концепция от автомобиля к транспортному средству.Moveableинтерфейс, объявленный в интерфейсеrun()метод, все классы транспортных средств реализуют этот интерфейс.
  • Для индивидуального производственного процесса мы можем произвести соответствующий автомобиль на заводе.
public interface Moveable {
    void run();
}

public class Car implements Moveable{

    public Car(){};//私有构造方法, 在类之外不能通过new获得本类对象了, 保证了单例

    public void run(){
        System.out.println("汽车正在向前跑...");
    }
}

public abstract class VehicleFactory {
    public abstract Moveable create();
}

public class CarFactory extends VehicleFactory {
    @Override
    public Moveable create() {
        return new Car();
    }
}

//Test
public static void main(String[] args) {
    VehicleFactory factory = new CarFactory();
    Moveable m = factory.create();
    m.run();
}

 

абстрактная фабрика

  • Давайте выкинем из головы картину простой фабрики и опишем другую реализацию фабрики.
  • Предположим, что водитель в начале не обычный водитель, ему нужен не только транспорт, чтобы добраться до определенного города, но и AK47, а также яблоко для непредвиденных нужд в дороге.
  • Поэтому нам нужно дать ему фабрику по производству этой серии продуктов.
  • Чтобы улучшить масштабируемость, мы также надеемся, что разные фабрики смогут производить разные серии продуктов, например, вышеупомянутая фабрика A производит автомобили, AK47 и яблоки, а фабрика B производит самолеты, ракетные установки и булочки Wangzai.
//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 {//交通工具的抽象类
    public abstract void run();
}

public abstract class Weapon {//武器的抽象类
    public abstract void fire();
}

public abstract class Food {//食物的抽象类
    public abstract void eat();
}

public class Car extends Vehiche{一种具体的交通工具
    @Override
    public void run() {
        System.out.println("小汽车启动...");
    }
}

public class AK47 extends Weapon {//一种具体的武器
    @Override
    public void fire() {
        System.out.println("哒哒哒...");
    }
}

public class Apple extends Food{//一种具体的食物
    @Override
    public void eat() {
        System.out.println("大口吃苹果...");
    }
}

//抽象工厂
public abstract class AbstractFactory {
    public abstract Vehiche createVehiche();
    public abstract Weapon createWeapon();
    public abstract Food createFood();
}

//抽象工厂的实现1
public class Factory1 extends AbstractFactory {
    @Override
    public Vehiche createVehiche() {
        return new Car();
    }

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

    @Override
    public Food createFood() {
        return new Apple();
    }
}

 

  • Подводя итог, каковы плюсы и минусы абстрактных фабрик и простых фабрик?
  • Абстрактная фабрика может производить серию продуктов и может легко заменить серию продуктов, но если вы хотите добавить еще одну разновидность в серию продуктов, это будет очень хлопотно.Например, добавление серии продуктов выше盔甲Абстрактный класс, то абстрактная фабрика и соответствующая реализация должны модифицировать исходный код.
  • Простая фабрика может гибко производить одну разновидность продукции, но если разновидностей много, возникнет проблема затопления фабрики.
  • Преимущества и недостатки этих двух дополняют друг друга, поэтому существует ли фабричная реализация, которая может быть совместима с преимуществами этих двух?springЗаводская реализация , дающая решение.

 

Весенний бобовый завод

  • Снова рассмотрим самый примитивный случай, естьMoveableинтерфейс, который имеетrunметод,CarКласс car реализует этот интерфейс.
public static void main(String[] args) {
    Moveable m = new Car();
    m.run();
}

public interface Moveable {
    void run();
}

public class Car implements Moveable{
    @Override
    public void run() {
        System.out.println("小汽车往前跑...");
    }
}
  • В bean factory Spring новые объекты не передаютсяnewКлючевое слово получается, но получается через конфигурационный файл.
  • Конкретный процесс: сначала прочитайте файл конфигурации, чтобы получить классclassобъект, а затем передатьclassОбъекты создают конкретные экземпляры объектов.
public static void main(String[] args) throws Exception {
    //获取配置文件
    Properties props = new Properties();
    props.load(Test.class.getClassLoader().getResourceAsStream("spring.properties"));
    //获取配置文件中配置的类
    String vehicheTypeName = props.getProperty("vehicheTypeName");
    //反射生成对应的对象
    Moveable m = (Moveable) Class.forName(vehicheTypeName).newInstance();
    m.run();
}

//spring.properties
vehicheTypeName=designPattern.factory.springFactory.Car

 

  • выше правильноspringМакет, используемый на фабрике бобов, ниже мы используем настоящийspringгенерироватьCarвозразите и сравните.
public static void main(String[] args) throws Exception {
    BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
    Vehiche v = (Vehiche)bf.getBean("v");
    v.run();
}

//配置文件
<bean id="v" class="designPattern.factory.Car">
</bean>
  • После сравнения мы обнаружили, что между простой фабрикой, которую мы написали, и бобовой фабрикой весны нет никакой разницы в использовании.springОн настолько прост в использовании, что давайте смоделируем реализацию фабрики bean-компонентов Spring.

 

Реализация фабрики Mock Spring

Аналоговый IOC

  • сказатьspringЯвляетсяbeanконтейнер, следующий код покажет, как он генерируетсяbean, и положиbeanПоместите в контейнер для пользователя, чтобы получить.
  • Идея относительно проста:
  1. СоздайтеBeanFactoryЗаводской интерфейс, добавление методовgetBean().
  2. СоздайтеBeanFactoryкласс реализацииClassPathXmlApplicationContextКонкретная реализация IOC будет показана в этом классе реализации.
  3. ClassPathXmlApplicationContextнужен одинcontainerКонтейнер хранит созданный объект bean, который используется здесьHashMapвыполнить.
  4. существуетClassPathXmlApplicationContextчитать в конструктореspringФайл конфигурации, используемый здесьdom4j, После прочтения конфигурационного файла согласноbeanизclassСвойства создаются с использованием отраженияbeanобъект, затем поместитеidа такжеbeanобъект какkeyа такжеvalueдобавил в контейнер.
  5. когда фабрика называетсяgetBean()метод, найдите соответствующий из контейнераbeanи вернуться.
public static void main(String[] args) throws Exception {
    BeanFactory bf = new ClassPathXmlApplicationContext("applicationContext.xml");
    Vehiche v = (Vehiche) bf.getBean("v");
    v.run();
}

//BeanFactory的实现类
public class ClassPathXmlApplicationContext implements BeanFactory {

    private Map<String, Object> container = new HashMap<>();//用于存放bean对象的容器
    
    //在构造方法中读取xml配置文件, 把bean对象都创建好并放入容器中
    public ClassPathXmlApplicationContext(String propAddr) throws 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;
    }
}

//极简BeanFactory
public interface BeanFactory {
    Object getBean(String beanId);
}

//xml中配置的bean
<bean id="v" class="designPattern.factory.Car">
</bean>