Шаблон проектирования — заводской шаблон

Java Шаблоны проектирования
Шаблон проектирования — заводской шаблон

Определение заводского шаблона

Значение модели фабричного метода (Factory Method) заключается в том, чтобы определить интерфейс фабрики объектов для создания продуктов, который будет откладываться до фактического создания их подклассов. Основной класс фабрики больше не отвечает за создание продукта, такого как роль абстрактной фабрики основного класса, он отвечает только за интерфейс конкретного подкласса фабрики, который должен быть достигнут, чтобы преимущества дальнейшей абстракции заключались в том, чтобы шаблон метода фабрики позволял системе не изменяет конкретную роль фабрики по внедрению новых продуктов в данных обстоятельствах.

Посмотрите на определение GOF как фабричного шаблона:

"Определите интерфейс для создания объекта, но позвольте подклассам решать, экземпляр какого класса создавать. Фабричный метод позволяет классу отложить создание экземпляра до подклассов" (Определите интерфейс для создания объекта в базовом классе, и пусть подклассы решат, какой класс создать экземпляр , Фабричные методы откладывают создание экземпляра класса до подклассов.)

Заводская классификация шаблонов

  • Простая фабрика, также известная как шаблон статического фабричного метода.
  • Шаблон фабричного метода (Factory Method).
  • Абстрактная фабрика (абстрактная фабрика).

сцены, которые будут использоваться

  1. Создайте объект продукта, который отправляет сообщения, например, отправляет сообщения пользователям через такие продукты, как электронная почта, текстовые сообщения и официальные учетные записи WeChat.
  2. getObject() из FactoryBean в Spring; различные bean-компоненты в spring. Его можно создать с помощью фабричного шаблона и добиться разделения зависимостей.

Преимущества фабричного шаблона

  • Разделение: разделение создания и использования объектов.
  • Уменьшите сложность кода: если создание объекта более сложное или его процесс состоит из большего количества шагов. Будет использоваться в нескольких местах, будет генерировать много повторяющегося кода.
  • Сокращение затрат на обслуживание: процесс создания управляется фабрикой.Когда бизнес меняется, нет необходимости переходить к месту, где объект А создается в коде, чтобы внести изменения, просто модифицируйте его на фабрике. Открытый закрытый принцип.

Простой заводской шаблон

На самом деле это не паттерн проектирования, он подходит для создания простых объектов, и объектов создается меньше. Клиент не заботится о процессе создания объекта.

Роль простого фабричного шаблона

  • Роль фабрики (Factory): ядро ​​простого фабричного шаблона, отвечающее за создание внутренней логики всех экземпляров и предоставление продуктов, необходимых для внешнего использования и создания.
  • Абстрактная роль продукта (Product): тип, созданный простой фабрикой.
  • Роль конкретного продукта: цель создания простого фабричного шаблона, все созданные объекты являются экземплярами конкретного класса, который играет эту роль.

Простая реализация заводского кода

Создайте интерфейс отправителя, который является ролью продукта

public interface Sender {
	
	/**
	 * 发送信息
	 * @param to 收件人
	 * @param msg 消息
	 * @return
	 */
	boolean send(String to, String msg);
	
}

Создайте конкретные продукты, а именно отправитель электронной почты, отправитель SMS.

public class MailSender implements Sender {

	@Override
	public boolean send(String to, String msg) {
		System.out.println("MailSender:收件人:" + to + ",消息为:" + msg);
		return true;
	}

}


public class SmsSender implements SenderService {

	@Override
	public boolean send(String to, String msg) {
		System.out.println("SmsSender:收件人:" + to + ",消息为:" + msg);
		return true;
	}

}

Создайте простую фабрику

/**
 * 工厂类,创建实例对象。缺点当字符串输错则得不到对象
 * @author unique
 *
 */
public class SendFactory {
	
	public Sender getObject(String type) {
		Sender sender = null;
		switch (type) {
		case "mail":
			senderService = new MailSender();
			break;
		case "sms":
			senderService = new SmsSender();
			break;
		default:
			System.out.println("请输入正确类型");
			break;
		}
		return sender;
	}

}

модульный тест

public class SimpleFactoryTest {
	
	public static void main(String[] args) {
		SendFactory factory = new SendFactory();
		Sender sender = factory.getObject("mail");
		sender.send("大兄弟", "你是最棒的!");
	}

}

недостаток

Когда мы добавляем новый класс продукта, нам нужно изменить метод getObject() в классе фабрики, который не соответствует принципу открытия-закрытия.

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

Один из наиболее часто используемых фабричных шаблонов.

Самое большое отличие от режима Simple Tolerance заключается в том, что мы больше не предоставляем единую фабрику для создания всех продуктов, а предоставляем двадцать разных фабрик для разных продуктов. То есть у каждого продукта есть соответствующая фабрика.

Применимая сцена

  • Класс не знает класс нужного ему объекта: в шаблоне метода фабрики клиенту не нужно знать имя класса конкретного класса продукта, а нужно знать только соответствующую фабрику, а конкретный объект продукта созданный конкретным фабричным классом; Клиент должен знать фабричный класс, который создает конкретный продукт.
  • Класс указывает, какой объект создавать, через свой подкласс: в шаблоне фабричного метода для абстрактного фабричного класса необходимо предоставить только интерфейс для создания продукта, а его подкласс определяет конкретный создаваемый объект, используя объектно-ориентированный полиморфизм. Секс и принцип Рихтера.
  • Задача создания объекта делегируется одному из нескольких фабричных подклассов.Клиент может использовать его, не заботясь о том, какой фабричный подкласс создает подкласс продукта, и динамически указывать его, когда это необходимо, и может хранить имя класса конкретного фабричного класса. в файле конфигурации или базе данных.

Роль шаблона фабричного метода

  • Роль абстрактной фабрики (Abstract Factory): это ядро ​​шаблона фабричного метода и не имеет ничего общего с приложением. Любой фабричный класс для объектов, созданных в схеме, должен реализовывать этот интерфейс.
  • Роль Concrete Factory: это класс конкретной фабрики, который реализует интерфейс абстрактной фабрики, содержит логику, тесно связанную с приложением, и вызывается приложением для создания определенного объекта продукта.
  • Роль абстрактного продукта (AbstractProduct): супертип объекта, созданный шаблоном фабричного метода, то есть общий родительский класс или общий интерфейс объекта продукта.
  • Конкретная роль продукта: эта роль реализует интерфейс, определенный абстрактной ролью продукта. Конкретный продукт создается конкретной конкретной фабрикой, и между ними часто существует взаимно однозначное соответствие.

пример кода

Основываясь на приведенной выше простой фабрике, давайте преобразуем ее. Создайте новую роль абстрактной фабрики

public interface SenderFactory {
	
	/**
	 * 生成对象
	 * @return
	 */
	public Sender getObject();

}

Добавьте фабричные классы SMS и электронной почты для реализации интерфейса абстрактной фабрики.

public class SendMailFactory implements SenderFactory {

	@Override
	public Sender getObject() {
		return new MailSender();
	}

}


public class SendSmsFactory implements SenderFactory {

	@Override
	public Sender getObject() {
		return new SmsSenderServiceImpl();
	}

}

тестовый код

public class Test {

	public static void main(String[] args) {
		SenderFactory senderFactory = new SendMailFactory();
		Sender sender = senderFactory.getObject();
		sender.send("大兄弟", "你是最棒的!");
	}

}

Абстрактный заводской узор

В паттерне фабричного метода у нас фактически есть подсознательное осознание. То есть мы производим однотипную продукцию. Шаблон абстрактной фабрики всего на один шаг дальше фабричного метода, в этом шаблоне класс фабрики может создавать не только один продукт, но и группу продуктов. Этот продукт будет опираться на несколько синтезирующих один. Например, у наших производителей компьютеров есть материнские платы и процессоры производства Intel и AMD. Это семейство продуктов включает ЦП и материнскую плату.

Шаблон абстрактной фабрики, как и шаблон фабричного метода, соответствует принципу открытого-закрытого. Но разница в том, что когда конкретный продукт добавляется в шаблон фабричного метода, необходимо добавить и соответствующую фабрику. Но шаблон абстрактной фабрики должен добавлять фабрику только тогда, когда добавляется конкретный продукт определенного типа. То есть фабрика шаблона фабричный метод может создать только один конкретный продукт. Фабрика абстрактного шаблона фабрики может создавать множество конкретных продуктов, принадлежащих к типу. Количество продуктов, созданных фабрикой, находится между шаблоном простой фабрики и шаблоном фабричного метода.

Применимая сцена

  • Как и в случае с фабричными методами, клиенту не нужно знать класс создаваемых им объектов.
  • Когда группа объектов требуется для совместного выполнения определенной функции, могут быть ситуации, когда несколько групп объектов выполняют разные функции. (продукты, принадлежащие к одному семейству продуктов)
  • Структура системы стабильна, и объекты не будут добавляться часто. (Поскольку после его добавления исходный код необходимо изменить, что не соответствует принципу открытого-закрытого)

Режим абстрактного фабричного метода Роль соответствует режиму фабричного метода

Наши компьютеры состоят из материнских плат, процессоров и памяти. Это все продукты, и теперь предоставляется фабрика для непосредственного производства ЦП и соответствующей материнской платы одновременно, избегая отдельного создания. Также известен как набор, серия.

Например, есть ЦП и материнские платы, произведенные заводами Intel, и ЦП и материнские платы, произведенные заводами AMD.

пример кода

Определить два продукта: процессор и материнская плата

public interface CPU {
    void calculate();
}

public interface Mainboard {
    void installCPU();
}

И конкретная реализация продуктов, таких как процессоры и материнские платы производства AMD и Intel.

public class AmdCpu implements CPU {
    /**
     * CPU的针脚数
     */
    private int pins = 0;

    public AmdCpu(int pins) {
        this.pins = pins;
    }

    @Override
    public void calculate() {
        System.out.println("AMD CPU的针脚数:" + pins);
    }
}


public class IntelCPU implements CPU {
    /**
     * CPU的针脚数
     */
    private int pins = 0;

    public IntelCPU(int pins) {
        this.pins = pins;
    }

    @Override
    public void calculate() {
        System.out.println("Intel CPU的针脚数:" + pins);
    }

}

public class AmdMainboard implements Mainboard {
    /**
     * CPU插槽的孔数
     */
    private int cpuHoles = 0;

    /**
     * 构造方法,传入CPU插槽的孔数
     *
     * @param cpuHoles
     */
    public AmdMainboard(int cpuHoles) {
        this.cpuHoles = cpuHoles;
    }

    @Override
    public void installCPU() {
        // TODO Auto-generated method stub
        System.out.println("AMD主板的CPU插槽孔数是:" + cpuHoles);
    }
}

public class IntelMainboard implements Mainboard {
    /**
     * CPU插槽的孔数
     */
    private int cpuHoles = 0;

    /**
     * 构造方法,传入CPU插槽的孔数
     *
     * @param cpuHoles
     */
    public IntelMainboard(int cpuHoles) {
        this.cpuHoles = cpuHoles;
    }

    @Override
    public void installCPU() {
        System.out.println("Intel主板的CPU插槽孔数是:" + cpuHoles);
    }

}

Затем мы сначала создаем роль абстрактной фабрики, которая может создавать определения фабричных методов для продуктов ЦП и материнских плат.

public interface MainboardCPUFactory {
    /**
     * 创建CPU对象
     *
     * @return CPU对象
     */
    public CPU createCpu();

    /**
     * 创建主板对象
     *
     * @return 主板对象
     */
    public Mainboard createMainboard();
}

Заводское определение Intel

public class IntelFactory implements MainboardCPUFactory {

    @Override
    public CPU createCpu() {
        return new IntelCPU(755);
    }

    @Override
    public Mainboard createMainboard() {
        return new IntelMainboard(755);
    }

}

завод АМД

public class AmdFactory implements MainboardCPUFactory {

    @Override
    public CPU createCpu() {
        return new AmdCpu(938);
    }

    @Override
    public Mainboard createMainboard() {
        return new AmdMainboard(938);
    }

}

Наконец, давайте протестируем

public class AbstactFactoryTest {
    public static void main(String[] args) {
        //使用因特尔工厂生产
        MainboardCPUFactory intelFactory = new IntelFactory();
        CPU cpu = intelFactory.createCpu();
        Mainboard mainboard = intelFactory.createMainboard();

        mainboard.installCPU();
        cpu.calculate();
    }
}

Распечатать

Intel主板的CPU插槽孔数是:755
Intel CPU的针脚数:755

Обратите внимание на публичный аккаунтJavaStormБолее захватывающим для вас.

JavaStorm