Фабричный шаблон - это шаблон создания, в котором вся логика создания объекта находится в фабричном классе. В этой статье я расскажу о том, как использовать его в приложении Spring Boot. Итак, начнем

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

public class Document {
}
public class Image {
}
public class Video {
}

Итак, в нашем приложении мы, конечно, можем напрямую создавать объекты вышеуказанного класса или мы можем назначить логику создания для фабрики просмотра. Мы выберем второй способ, поскольку они реализуют общий интерфейс, и клиенту не нужно знать логику создания. Перед тем, как продолжить, нам также необходимо проверить классы просмотра вышеуказанных моделей. Во-первых, вы можете увидеть интерфейс средства просмотра, который предоставляет общие методы для всех средств просмотра, getType и view. getType будет использоваться для реализации фабрики, а представление будет основной логикой для просмотра объекта.

public interface Viewer<T> {
    ViewerType getType();
    void view(T object);
}

Ниже вы можете увидеть, как Viewer реализует классы.

DocumentViewer

@Component
public class DocumentViewer implements Viewer<Document>{

    @Override
    public ViewerType getType() {
        return ViewerType.DOCUMENT;
    }

    @Override
    public void view(Document object) {
        // some logic to view image,
        // we do not care the implementation here
    }
}

ImageViewer

@Component
public class ImageViewer implements Viewer<Image> {

    @Override
    public ViewerType getType() {
        return ViewerType.IMAGE;
    }

    @Override
    public void view(Image object) {
        // some logic to view image,
        // we do not care the implementation here
    }
}

VideoViewer

@Component
public class VideoViewer implements Viewer<Video> {

    @Override
    public ViewerType getType() {
        return ViewerType.VIDEO;
    }

    @Override
    public void view(Video object) {
        // some logic to view image,
        // we do not care the implementation here
    }
}

и перечисление ViewerType

public enum ViewerType {
    DOCUMENT,
    IMAGE,
    VIDEO
}

Теперь перейдем к основной части - классу factory. Во-первых, вы можете увидеть viewerMap. На этой карте мы будем хранить зрителей, чтобы не создавать их каждый раз, когда вызывается метод getViewer для создания желаемого объекта. Затем в нашем конструкторе мы получим список классов (Spring предоставляет его нам), реализующих интерфейс Viewer, и затем мы поместим их на нашу карту. Основная часть этого класса, касающаяся клиента, - это метод getViewer. Когда этот метод вызывается с желаемым типом, он сначала извлекает средство просмотра с карты. Если это нулевой объект, это означает, что мы отправляем ошибочный тип средства просмотра, что означает, что этот вид средства просмотра никогда не реализуется. Если такой ситуации не возникает, мы можем продолжить и вернуть зрителя.

@Component
public class ViewerFactory {
    private static final Map<ViewerType, Viewer> viewerMap = new EnumMap<>(ViewerType.class);

    @Autowired
    private ViewerFactory(List<Viewer> viewers) {
        for (Viewer viewer : viewers) {
            viewerMap.put(viewer.getType(), viewer);
        }
    }

    public static <T> Viewer<T> getViewer(ViewerType viewerType) {
        Viewer<T> viewer = viewerMap.get(viewerType);
        if (viewer == null) {
            throw new IllegalArgumentException();
        }
        return viewer;
    }
}

Мы можем использовать его следующим образом

ViewerFactory.getViewer(ViewerType.DOCUMENT).view(new Document());

Я также хочу поделиться другим способом реализации класса Factory следующим образом. В этом случае я пропустил статическое поле и метод и использовал factory, автоматически подключив его к нужному классу.

@Component
public class ViewerFactory {
    private final Map<ViewerType, Viewer> viewerMap = new EnumMap<>(ViewerType.class);

    @Autowired
    private ViewerFactory(List<Viewer> viewers) {
        for (Viewer viewer : viewers) {
            viewerMap.put(viewer.getType(), viewer);
        }
    }

    public <T> Viewer<T> getViewer(ViewerType viewerType) {
        Viewer<T> viewer = viewerMap.get(viewerType);
        if (viewer == null) {
            throw new IllegalArgumentException();
        }
        return viewer;
    }
}

Сервис для его использования

@Service
public class SomeService {
    ViewerFactory viewerFactory;

    @Autowired
    public SomeService(ViewerFactory viewerFactory) {
        this.viewerFactory = viewerFactory;
    }

    public void handleView() {
        viewerFactory.getViewer(ViewerType.DOCUMENT).view(new Document());
    }
}

Как видите, в приложениях Spring Boot очень легко реализовать фабричный шаблон. Надеюсь, статья вам понравится и вы найдете ее полезной. Увидимся в следующий раз :)