Вы понимаете заводскую схему?

Java задняя часть Шаблоны проектирования Java EE

предисловие

Только лысина может стать сильнее

Оглядываясь назад на фронт:

Вчера я написал шаблон singleton, а сегодня пришло время написать шаблон factory~

фабричный образец яя лично думаю, что это сложнее понять, если вы общались | слышали | видели эту модель, ученики, скорее всего, подумают: я самnewОбъект получается просто прекрасным, простым и быстрым. Вам нужна ваша заводская выкройка? Чтобы построить фабрику, нужно много кода~

Много информации в интернете разъясняет: преимущество заводской модели в том, чторазъединение. я верю всемразъединениеЭто слово не является незнакомым, так в чем же польза от развязки?

эта статьяПопробуйте объяснитьЗачем использовать фабричный шаблон, каковы преимущества использования фабричного шаблона и каковы различия между тремя формами, полученными из фабричного шаблона~~

Тогда давайте начнем Если что-то не так, я надеюсь простить меня много, и не стесняйтесь поправлять меня в области комментариев!

Обзор фабричного шаблона

В книге «Дзен шаблонов проектирования» фабричный шаблон разделен на две главы:

  • Шаблон фабричного метода
    • (ps: в нем упоминается простой заводской шаблон)
  • Абстрактный заводской узор

Большая часть информации в интернете делит заводскую модель натрисвоего рода:

  • Простой/статический заводской шаблон
  • Шаблон фабричного метода
  • Абстрактный заводской узор

Прочитав приведенное выше описание, вы хотите меня убить, что за птица? Не волнуйтесь, я расскажу о них один за другим ниже~

1.1 Зачем использовать заводской шаблон?

Подумайте, почему мы используем шаблон factory? Вот мой простой пример:

Мы будем часто использовать операцию файлового ввода-вывода, поэтому объект BufferedReaderчасто создаютиз:


    // 创建一个BufferedReader对象
    BufferedReader bf = new BufferedReader(new FileReader(new File("aa.txt")));

Ты сказал беда? На самом деле это не хлопотно, всего одна строчка кода, где беда~ Если студенты, не знакомые с IO-потоками, не настолько умны, создание BufferedReader может быть следующим кодом:


        File file = new File("aa.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);

Ты сказал беда? На самом деле это не хлопотно, не правда ли, всего три строчки кода, в чем беда~ Если это приложениеИспользуется во многих классахДля объектов BufferedReader эти три строки кода записываются в каждом классе. Тогда вы говорите беда? Это должно быть хлопотно, мне все еще нужно подумать об этом...

Видно, что для создания объекта BufferReader требуется объект FileReader, а для объекта FileReader требуется объект File. ТотСоздание этого объекта BufferReader более проблематично(Код не хлопотный, но хлопотный со структурной точки зрения)!

Хотя это более хлопотно, мы все же можем его использовать, и мы можем его использовать! Итак, мы пошли писать код.Теперь есть три класса, которым нужно читать и записывать файлы, поэтому у них такой код:


public class FileOperateA {

    public static void main(String[] args) throws FileNotFoundException {
        File file = new File("aa.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);


        // 读写文件....
    }
}

В это время: Выше сказано, я хочуИзмените на LineNumberReader для чтения и записи, есть этот спрос! Итак, что мы можем сделать как кодировщики? Отчаялся и должен это сделать.

  • Парень, который не знаком с IDE, просто поменял BufferedReader на LineNumberReader один за другим, теперь только 3 класса используют BufferedReader, и только 6 раз. (ps: Что, если он используется во многих местах?)
  • Парень, знакомый с IDE, заменит рефакторинг глобально, вот и все!

эй, писать код - куча дерьма... есть ли способ сделатьСоздание объектов стало прощеиМожет быть очень удобно при изменении объектовШерстяная ткань?

  • Эй, заводской режим подойдет.

снова изОбъектно-ориентированная перспектива: Не слишком ли сложно для меня создать BufferReader для класса, который манипулирует файлами? (обязанности не распределены должным образом)

  • Передача на фабрику создания объектов очень объектно-ориентирована!

1.2 Испытайте заводской режим

Что такое фабрика? Вся наша продукция передается на завод для производства! Откуда взялся iPhone 5s, которым я сейчас пользуюсь? Собран на заводе Foxconn. Нужно ли мне знать, как iphone5s собирается в Foxconn? ненужный.

Давай, давайте переделаем приведенный выше пример. Сначала мы создаем фабричный класс, который можетСоздание объектов Reader!


// 创建Reader对象的工厂
public class ReaderFactory {
    public static Reader getReader() throws FileNotFoundException {
        File file = new File("aa.txt");
        FileReader fileReader = new FileReader(file);
        BufferedReader reader = new BufferedReader(fileReader);
        return reader;
    }
}

Затем нам нужно получить объект BufferReaderВор простойв настоящее время:


public class FileOperateA {

    public static void main(String[] args) throws FileNotFoundException {


        //-------我有工厂了,还用自己搞吗?不用了!
        //File file = new File("aa.txt");
        //FileReader fileReader = new FileReader(file);
        //BufferedReader bufferedReader = new BufferedReader(fileReader);
        //-------我有工厂了,还用自己搞吗?不用了!

		// 用工厂来创建出对象
        Reader reader = ReaderFactory.getReader();

        // 读写文件....
    }
}

завод будет намПроцесс созданного объекта заблокирован!

На данный момент я хочу перейти на LineNumberReader, как играть? существуетМеняй на заводеДостаточно:

наш абонентFileOperateA|FileOperateB|FileOperateCЭти классы вообще не нужно менять!

1.3 Преимущества использования фабричных методов

Из приведенного выше опыта фабричного шаблона мы можем видеть, что:

  • Мы изменили конкретный класс реализации, предназначенный для клиента (вызывающего)вообще без модификации.
  • если мы используемnewспособ создания объекта, то мы говорим:newВыходящий объект и текущий клиент (вызывающий)связь!
    • То есть текущий клиент (вызывающий)зависит отэтоnewвне объекта!

В этом преимущество развязки!

Позвольте мне записать код, который я написал в предыдущей практике:

У меня есть DaoFactory, логика очень простаСпециальное создание объектов Даода~

Затем на уровне службы вы можетеИспользуйте фабрику для инициализации желаемого объекта Dao~

На данный момент наши объекты Службы и Даонизкое сцеплениеда~

  • Всеможет не увидеть никакой выгоды, также есть много строк или что-то в этом роде~~

В слоях Service и Controller я также получил ServiceFactory.Согласно потребностям бизнеса на тот момент (добавление разрешений), яОчень гибкий при создании сервисовв настоящее время:

2. Как использовать заводской шаблон

Как я уже говорил в начале, фабричный паттерн можно разделить на три категории:

  • Простой/статический заводской шаблон
  • Шаблон фабричного метода
  • Абстрактный заводской узор

Далее я покажу разницу между каждым заводским режимом один за другим ~

Все три режима начинаются с:Java3y хочет купить пример для объяснения~

2.1 Шаблон фабричного метода

Многие блоги объясняют фабричный шаблон в следующем порядке: простой/статический фабричный шаблон, фабричный метод и абстрактный фабричный шаблон. Я думаю, что легче понять порядок в книге, потому что простой/статический фабричный шаблон находится в шаблоне фабричного метода.уменьшать, абстрактный фабричный шаблон является расширением фабричного метода.усилить.

  • Итак, сначала я расскажу о шаблоне фабричного метода.

Java3y скучно писать код каждый день, я хочу купить домашнее животное, чтобы сопровождать меня. Так чтоСходите в зоомагазин, чтобы увидеть домашних животных~~~

Как зоомагазин, он утверждает, что у него есть все виды домашних животных! Итак, когда хозяин дал объявление, он сказал: Мой зоомагазинлюбой питомец!

Так родилась фабрика по производству питомцев~


// 号称什么宠物都有
public interface AnimalFactory {

	// 可以获取任何的宠物
	Animal createAnimal();
}

Конечно, обычные домашние животные должны быть в наличии, и некоторые из них помещаются в магазин, чтобы заполнить витрину, а некоторые специальные домашние животные скажут покупателям, что нужно время, чтобы запастись ~

  • Итак, у нас есть фабрика по постройке кошек и собак (наследует фабрику для всех питомцев)

Фабрика кошек:


// 继承着宠物工厂
public class CatFactory implements AnimalFactory {
    @Override
    // 创建猫
    public Animal createAnimal() {
        return new Cat();
    }

}

То же самое касается собачьей фабрики:


// 继承着宠物工厂
public class DogFactory implements AnimalFactory {

	// 创建狗
	@Override
	public Animal createAnimal() {
		return new Dog();
	}

}

Ну, есть еще наши классы сущностей: кошки, собаки, животные (полиморфизм: кошки и собаки — это животные, которые могут быть напрямую представлены животными)

Класс животных:


public abstract class Animal {

	// 所有的动物都会吃东西
	public abstract void eat();
}

Класс сущности кошки:


public class Cat extends Animal {
	
	// 猫喜欢吃鱼
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}

}

Класс сущности собаки:


public class Dog extends Animal {

	// 狗喜欢吃肉
	@Override
	public void eat() {
		System.out.println("狗吃肉");
	}

}

Итак, теперь Java3y хочет собаку и сказал владельцу зоомагазина, что владелец зоомагазина пошел искать собаку и вернулся:


    // 去找狗工厂拿一只狗过来
    AnimalFactory f = new DogFactory();

    // 店主就拿到了一只狗给Java3y
    Animal a = f.createAnimal();
    a.eat();
    System.out.println("关注公众号:Java3y");

Итак, теперь Java3y хочет кошку и сказал владельцу зоомагазина, что владелец зоомагазина пошел искать кошку и вернулся:


    // 去找猫工厂拿一只猫过来
    AnimalFactory ff = new CatFactory();

	// 店主就拿到了一只猫给Java3y
    Animal aa = ff.createAnimal();
    aa.eat();
    System.out.println("关注公众号:Java3y");

Что, если Java3y скажет, что сейчас хочет ящерицу? без проблем, лавочникПостроить фабрику ящерицЭто хорошо~~


        // 要买蜥蜴..
        AnimalFactory fff = new LizardFactory();
        Animal aaa = ff.createAnimal();
        aaa.eat();

преимущество:

  • 1: Клиент не должен нести ответственность за создание объекта,Уточнены обязанности каждого класса
  • 2: если естьдобавлены новые объекты,нужно всего лишьДобавьте класс бетона и класс бетонной фабрикиПросто
  • 3:Не влияет на существующий код, последующее обслуживание упрощается, а масштабируемость системы повышается

недостаток:

  • 1: требует дополнительного кодирования и увеличивает рабочую нагрузку

Диаграмма класса фабричного метода:

2.2 Простой/статический заводской шаблон

Теперь бизнес зоомагазина не очень хорош, он известен как «все домашние животные», это раздуто~~ Итак, владелецПродаются только два обычных питомца.

  • Поскольку есть только два вида домашних животных, нет необходимости иметь «фабрику кошек» и «фабрику собак», достаточно одной фабрики кошек и собак!

Итак, наша фабрика выглядит так:


public class AnimalFactory {
    public static Dog createDog() {
        return new Dog();
    }

    public static Cat createCat() {
        return new Cat();
    }


    // 外界想要猫要狗,这里创建就好了
    public static Animal createAnimal(String type) {
        if ("dog".equals(type)) {
            return new Dog();
        } else if ("cat".equals(type)) {
            return new Cat();
        } else {
            return null;
        }
    }
}

Три сущности остаются прежними (животное, кошка, собака) …

Затем, когда Java3y идет в зоомагазин, чтобы купить кошек и собак, он говорит боссу, что я хочу кошек и собак:


		// 拿到狗
        Animal A = AnimalFactory.createAnimal("dog");
        A.eat();

		// 拿到猫
        Animal C = AnimalFactory.createAnimal("cat");
        C.eat();

Теперь возникает вопрос:

  • 1: Я хочу свинью,Но в моем фабричном классе нет свиней
  • 2: я пойдуизменятькод, который может создавать объекты свиньи
  • 3: Далее, я хочу других животных
  • 4: я все еще долженизменятькод
  • 5...................
  • 6: Это недостаток простого фабричного класса:Когда требования изменятся, я изменю код.

Преимущества простого фабричного класса также очевидны: IСоздание объектов на бетонном заводе, объем кода небольшой.

2.3 Шаблон абстрактной фабрики

Шаблон абстрактной фабрики более сложен, мыОбщие приложения не могут быть написаны. Позвольте мне сначала кратко описать требования:

  • Сейчас это очень популярно, а еще в кошачьей и собачьей индустрии витает «гендерный ветер».
    • Некоторым нравится мужчина
    • некоторые как матери

Тогда наши кошки и собаки бывают всех полов, мужского или женского пола~~

  • Раньше мы открывали фабрику для каждого животного в режиме фабричного метода.Если животных слишком много, будет много фабрик~
  • Итак, теперь мы можемизвлекать: Каждое животное либо самец, либо самка~
  • Так что у нас достаточно двух заводов!

Конкретный код таков:

Наша самая большая фабрика по-прежнему определяет, какое животное создается


public interface AnimalFactory {
	Animal createDog();
	Animal createCat();
}

Фабрика по созданию кошек и собак женского пола:


public class FemaleAnimalFactory implements AnimalFactory {

    // 生产母狗和母猫
    @Override
    public Animal createDog() {
        return  new FemaleDog();
    }

    @Override
    public Animal createCat() {
        return new FemaleCat();
    }

}

Фабрика по созданию котов и собак:


public class MaleAnimalFactory implements AnimalFactory {
    
    // 生产公狗和公猫

    @Override
    public Animal createDog() {
        return new MaleDog();
    }

    @Override
    public Animal createCat() {
        return new MaleCat();
    }

}

ЭтоОбщее поведение, которое есть у всех животных:


public abstract class Animal {

	// 所有的动物都会吃东西
	public abstract void eat();

	// 所有的动物都有性别
	public abstract void gender();
}

Вот общее поведение, которое есть у всех кошек:


public abstract class Cat extends Animal {
	// 猫喜欢吃鱼
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}
}

Вот общее поведение, которое есть у всех собак:

public abstract class Dog extends Animal {

	// 狗喜欢吃肉
	@Override
	public void eat() {
		System.out.println("狗吃肉");
	}

}

Кошки делятся на кошек-самцов и кошек-самок. Собаки делятся на самцов и самок:

public class FemaleCat extends Cat {

    public void gender() {
        System.out.println("I am a female Cat");
    }

}

.....

Проще говоря: фабрика паттерна фабричный метод заключается в созданиисвоего родапродукты, а абстрактная фабрика должна создаватьодин типпродукт.

  • Класс продуктов, который мы называемСемейство продуктов.
    • Кошки — это один вид, как и собаки. Итак, AnimalFactory определяет два типа продуктов --->Animal createDog();иAnimal createCat();
  • продуктструктура наследованияназови этокачество продукта.
    • Все животные едят, и все они занимаются сексом, что является наиболее распространенным. Итак, Animal определяет два абстрактных метода:public abstract void eat();иpublic abstract void gender();
    • Все собаки едят мясо, поэтому собака сделала это возможнымeat()метод
      • Собаки делятся на собак мужского пола и собак женского пола, поэтому определены два класса FemaleDog и MaleDog, чтобы наследовать Dog и реализоватьgender()метод
    • Все коты едят рыбу, поэтому это сделал Котeat()метод
      • Кошки делятся на кошек мужского пола и кошек женского пола, поэтому определены два класса FemaleCat и MaleCat, чтобы наследовать Cat и реализоватьgender()метод
  • Конкретный заводПроизводство для множественной иерархии продуктов.
    • Итак, FemaleAnimalFactory определяетcreateDog()иcreateCat()Рождение самок собак и кошек
    • Итак, MaleAnimalFactory определяетcreateDog()иcreateCat()Производство кобелей и обыкновенных кошек
  • Найдите женскую фабрику для создания женских кошек и собак и мужскую фабрику для создания самцов кошек и самцов собак.


    public static void main(String[] args) {


        // 需要性别为母的就去找母工厂
        AnimalFactory af = new FemaleAnimalFactory();

        // 需要一只母猫
        af.createCat().gender();

        // 需要一只母狗
        af.createDog().gender();

        System.out.println("-------------关注公众号:Java3y-------------------------");

        // 需要性别为公的就去找公工厂
        AnimalFactory aff = new MaleAnimalFactory();

        // 需要一只公狗
        aff.createDog().gender();

        // 需要一只公猫
        aff.createCat().gender();

    }

Эффект:

Вот диаграмма классов абстрактного шаблона factory:

Абстрактный фабричный шаблонЕще один уровень абстракции, уменьшающий количество фабрик.

Недостатки абстрактных фабрик также очевидны:

  • трудныйРасширить семейство продуктов---> Если я снова хочу домашних свиней
    • Затем мне нужно изменить классы AnimalFactory, FemaleAnimalFactory и MaleAnimalFactory~

3. Резюме

В целом мыИспользуйте простой заводской шаблон больше, режим фабричного режима будет иметь относительно большой объем кода, а абстрактный фабричный режим будет использоваться только тогда, когда бизнес относительно большой (если у вас есть метод лучшего понимания, вы можете оставить сообщение в области комментариев и обменяться идеи вместе~~)

  • Также отлично использовать заводской режим с отражением~

Использованная литература:

Если в статье есть какие-либо ошибки, пожалуйста, поправьте меня, и мы сможем общаться друг с другом. Учащиеся, привыкшие читать технические статьи в WeChat и желающие получить больше ресурсов по Java, могутОбратите внимание на публичный аккаунт WeChat: Java3y.

Оглавление Навигация по статьям: