#java #abstract-factory
#java #абстрактная фабрика
Вопрос:
Я хотел бы создать абстрактную фабрику. вот что я попробовал.
// абстрактный рабочий класс
public abstract class Worker {
String phoneNumber;
String firstName;
String lastName;
String workerType;
String ifu;
String imageParth;
//....
public String getWorkerType() {
return workerType;
}
}
// Класс электрика, который расширяет worker
package worker.domain.worker;
public class Electrician extends Worker{
public Electrician() {}
public Electrician(String phoneNumber, String firstName, String lastName, String ifu, String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu,workerType, imageParth);
}
public String getWorkerType() {
return "Electrician";
}
}
// Класс Мейсона
package worker.domaine.worker;
public class Mason extends Worker{
public Mason() {};
public Mason(String phoneNumber, String firstName, String lastName, String ifu,String workerType,
String imageParth) {
super(phoneNumber, firstName, lastName, ifu, workerType, imageParth);
}
String getworkerType() {
return "Mason";
}
}
// interface WorkerAbstractFactory
package worker.domaine.worker;
public interface WorkerAbstractFactory {
Worker createWorker(String typeWorker);
}
//
public class WorkerFactory implements WorkerAbstractFactory{
@Override
public Worker createWorker(String typeWorker) {
Worker worker = null;
if(worker != null) {
switch (typeWorker) {
case "Electrician":
Electrician electrician =new Electrician();
electrician = new Electrician (electrician.getPhoneNumber(), electrician.getFirstName(), electrician.getLastName(), electrician.getIfu(), electrician.getWorkerType(),electrician.getImageParth());
case "Mason":
Mason mason =new Mason();
mason = new Mason (mason.getPhoneNumber(), mason.getFirstName(), mason.getLastName(), mason.getIfu(), mason.getworkerType(),mason.getImageParth());
}}
// класс приложения
public class WorkerFactoryProvider {
public static WorkerAbstractFactory getWorkerFactory(String workerCategory) {
//WorkerFactory workerFactory = new WorkerFactory();
WorkerFactory workerFactory = new WorkerFactory();
if (workerCategory != null) {
switch (workerCategory) {
case "Electrician":
Worker worker1 = workerFactory.createWorker("Electrician");
worker1.getWorkerType();
String a=worker1.getWorkerType();
System.out.println(a);
case "Mason":
Worker worker2 = workerFactory.createWorker("Mason");
worker2.getWorkerType();
String b=worker2.getWorkerType();
System.out.println(b);
}
}
return null;
}
как вы думаете, это может так работать? теперь, если я действительно хочу конкретный объект, как это можно сделать? потому что я хотел бы написать, например, метод для расчета заработной платы каждого работника в зависимости от типа, например, как я мог бы использовать свою абстрактную фабрику в методе, чтобы возвращать мне каждый тип.
Комментарии:
1. Примечание: вам необходимо передать все эти поля PhoneNumber и т.д. на фабрику, чтобы она могла создавать экземпляр Worker. В качестве альтернативы, пусть фабрика создаст WorkerBuilder, соответствующий базовому типу.
2. Добро пожаловать в StackOverflow. Ваш первый вопрос: «Как вы думаете, это может так работать», запрашивает мнение. Есть ли (каламбур) конкретный вопрос, который вы хотели бы задать?
Ответ №1:
У вас есть единая иерархия классов рабочих типов. Для их создания вы можете просто использовать отдельный класс factory, здесь вам не нужна абстрактная фабрика. Например, этого было бы достаточно:
public class WorkerFactory {
public Worker createWorker(String workerType) {
switch (workerType) {
case "Electrician": return new Electrician();
case "Mason": return new Mason();
}
}
}
Шаблон абстрактной фабрики более сложный и позволяет вводить разные конкретные фабрики для связанных иерархий объектов, так что клиенту не нужно знать о разнице. Например, у вас может быть абстрактный TransportationFactory:
interface Transportation {
void travelTo(String destination);
}
interface TransportationFactory {
Transportation simple();
Transportation luxurious();
}
И две конкретные реализации (соответствующие двум разным, но похожим иерархиям классов):
class WaterTransportationFactory {
Transportation simple() {
return new Kayak();
}
Transportation luxurious() {
return new Yacht();
}
}
И:
class LandTransportationFactory {
Transportation simple() {
return new Bike();
}
Transportation luxurious() {
return new RaceCar();
}
}
Преимущество этого шаблона в том, что клиент может быть настроен на использование водного или наземного транспорта (или нового воздушного транспорта, который будет добавлен позже) без необходимости внесения каких-либо изменений:
class Client {
private TransportationFactory transportationFactory;
public Client(TransportationFactory transportationFactory) {
this.transportationFactory = transportationFactory;
}
public void travel(String destination) {
transportationFactory.simple().travelTo(destination);
}
public void travelInStyle(String destination) {
transportationFactory.luxurious().travelTo(destination);
}
}
РЕДАКТИРОВАТЬ: вы можете изменить простые / роскошные методы, чтобы они соответствовали стилю вашего примера с getWorkerType
помощью метода. Я предпочитаю избегать условной логики, если это возможно, и позволяю созданным классам самим определять их доступность. Это еще больше разъединяет, позволяя добавлять элементы иерархии с минимальными изменениями кода:
enum TransportationType {
SIMPLE, LUXURIOUS
}
interface Transportation {
void travelTo(String destination);
// allow the class to specify its own type
TransportationType getType();
}
// intermediate interface to distinguish Water from Land
interface WaterTransportation extends Transportation {
}
class Kayak implements WaterTransportation {
void travelTo(String destination) {
// splash splash
}
TransportationType getType() {
return TransportationType.SIMPLE;
}
}
class WaterTransportationFactory {
private WaterTransportation[] waterTransportations;
// Inject all available beans implementing WaterTransportation
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportation[] waterTransportations) {
this.waterTransportations = waterTransportations;
}
public Transportation create(TransportationType type) {
for(WaterTransportation waterTransportation : waterTransportations) {
if (waterTransportation.getType() == type) {
// we are returning the same instance every time
// this could be ok for singleton beans
// but if you really need a fresh instance you could use builders (see below)
return waterTransportation;
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" type);
}
}
Альтернатива со сборщиками:
KayakBuilder implements WaterTransportationBuilder {
KayakBuilder name(String name) { ... };
KayakBuilder weight(String weightInKg) { ... };
KayakBuilder year(String yearBuilt) { ... };
KayakBuilder speed(String averageSpeed) { ... };
Kayak build() { return kayak; }
}
Для получения дополнительной информации о сборщиках см. Это Полное Изложение шаблона Builder
class WaterTransportationFactory {
private WaterTransportationBuilder[] builders;
// Inject all available WaterTransportationBuilders
// e.g. using Spring or some other dependency injection mechanism
public WaterTransportationFactory(WaterTransportationBuilder[] builders) {
this.builders = builders;
}
// extra arguments can be passed to build the instance
public Transportation create(TransportationType type, String name, int weightInKg, int yearBuilt, int averageSpeed) {
for(WaterTransportationBuilder builder: builders) {
if (builder.getType() == type) {
return builder
.name(name)
.weight(weightInKg)
.year(yearBuilt)
.speed(averageSpeed)
.build();
}
}
throw new IllegalArgumentException("No implementation for WaterTransportation type=" type);
}
}