Skip to content

factory: clean-up #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions abstract-factory/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id 'org.springframework.boot' version '2.5.1'
id 'io.spring.dependency-management' version '1.1.0'
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
}
15 changes: 15 additions & 0 deletions abstract-factory/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
### Why use the Abstract Factory Pattern

- Use the Abstract Factory when your code needs to work with various families of related products, but you don’t want it to depend on the concrete classes of those products
- The Abstract Factory provides you with an interface for creating objects from each class of the product family. As long as your code creates objects via this interface, you don’t have to worry about creating the wrong variant of a product which doesn’t match the products already created by your app.

#### Pros

- You can be sure that the products you’re getting from a factory are compatible with each other.
- You avoid tight coupling between concrete products and client code.
- Single Responsibility Principle. You can extract the product creation code into one place, making the code easier to support.
- Open/Closed Principle. You can introduce new variants of products without breaking existing client code.

#### Cons

- The code may become more complicated than it should be, since a lot of new interfaces and classes are introduced along with the pattern.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.agileactors.abstractfactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AbstractFactoryApplication {

public static void main(String[] args) {
SpringApplication.run(AbstractFactoryApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.agileactors.abstractfactory.api;

import com.agileactors.abstractfactory.dto.TransportationDto;
import com.agileactors.abstractfactory.dto.TransportationInput;
import com.agileactors.abstractfactory.mapper.TransportationMapper;
import com.agileactors.abstractfactory.service.transportation.TransportationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/transportation")
public class TransportationController {

private final TransportationService transportationService;

private final TransportationMapper transportationMapper;

@PostMapping(value = "/{era}")
@ResponseStatus(HttpStatus.OK)
public String transportCargo(@RequestBody TransportationInput transportationInput,
@PathVariable String era) {

TransportationDto transportationDto = transportationMapper.toDto(transportationInput);

return transportationService.transportCargo(transportationDto, era);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.agileactors.abstractfactory.dto;

import java.math.BigDecimal;

public record TransportationDto(String cargo, Double quantity, BigDecimal cost,
String pointOfDeparture, String destination) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.agileactors.abstractfactory.dto;

import java.math.BigDecimal;

public record TransportationInput(String cargo, Double quantity, BigDecimal cost,
String pointOfDeparture, String destination) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.agileactors.abstractfactory.enums;

public enum MeansOfTransportationEnum {
SHIP,
AIRPLANE,
TRUCK
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.agileactors.abstractfactory.factory;

import com.agileactors.abstractfactory.enums.MeansOfTransportationEnum;
import com.agileactors.abstractfactory.factory.abs.MeansOfTransportationOfEraFactory;
import com.agileactors.abstractfactory.factory.concrete.PostwarFactory;
import com.agileactors.abstractfactory.factory.concrete.PrewarFactory;
import com.agileactors.abstractfactory.meansoftransportation.MeansOfTransport;

public class Factory {

private Factory() {
}

public static MeansOfTransport getMeansOfTransport(
MeansOfTransportationEnum meansOfTransportationEnum,
MeansOfTransportationOfEraFactory factory) {

return switch (meansOfTransportationEnum) {
case AIRPLANE -> factory.createAirplane();
case SHIP -> factory.createShip();
default -> factory.createTruck();
};
}

public static MeansOfTransportationOfEraFactory getFactoryOfEra(String era) {
if ("prewar".equals(era)) {
return new PrewarFactory();
}
return new PostwarFactory();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.agileactors.abstractfactory.factory.abs;

import com.agileactors.abstractfactory.meansoftransportation.airplane.Airplane;
import com.agileactors.abstractfactory.meansoftransportation.ship.Ship;
import com.agileactors.abstractfactory.meansoftransportation.truck.Truck;

public interface MeansOfTransportationOfEraFactory {
Ship createShip();

Airplane createAirplane();

Truck createTruck();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.agileactors.abstractfactory.factory.concrete;

import com.agileactors.abstractfactory.factory.abs.MeansOfTransportationOfEraFactory;
import com.agileactors.abstractfactory.meansoftransportation.airplane.Airplane;
import com.agileactors.abstractfactory.meansoftransportation.airplane.PostwarAirplane;
import com.agileactors.abstractfactory.meansoftransportation.ship.PostwarShip;
import com.agileactors.abstractfactory.meansoftransportation.ship.Ship;
import com.agileactors.abstractfactory.meansoftransportation.truck.PostwarTruck;
import com.agileactors.abstractfactory.meansoftransportation.truck.Truck;

public class PostwarFactory implements MeansOfTransportationOfEraFactory {
@Override
public Ship createShip() {
return new PostwarShip();
}

@Override
public Airplane createAirplane() {
return new PostwarAirplane();
}

@Override
public Truck createTruck() {
return new PostwarTruck();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.agileactors.abstractfactory.factory.concrete;

import com.agileactors.abstractfactory.factory.abs.MeansOfTransportationOfEraFactory;
import com.agileactors.abstractfactory.meansoftransportation.airplane.Airplane;
import com.agileactors.abstractfactory.meansoftransportation.airplane.PrewarAirplane;
import com.agileactors.abstractfactory.meansoftransportation.ship.PrewarShip;
import com.agileactors.abstractfactory.meansoftransportation.ship.Ship;
import com.agileactors.abstractfactory.meansoftransportation.truck.PrewarTruck;
import com.agileactors.abstractfactory.meansoftransportation.truck.Truck;

public class PrewarFactory implements MeansOfTransportationOfEraFactory {
@Override
public Ship createShip() {
return new PrewarShip();
}

@Override
public Airplane createAirplane() {
return new PrewarAirplane();
}

@Override
public Truck createTruck() {
return new PrewarTruck();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.agileactors.abstractfactory.mapper;

import com.agileactors.abstractfactory.dto.TransportationDto;
import com.agileactors.abstractfactory.dto.TransportationInput;
import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface TransportationMapper {
TransportationDto toDto(TransportationInput input);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.agileactors.abstractfactory.meansoftransportation;

public interface MeansOfTransport {

public void checkCargo(String cargo);

public void loadCargo(Double quantity);

public void sendToDestination(String destination);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.agileactors.abstractfactory.meansoftransportation.airplane;

import com.agileactors.abstractfactory.meansoftransportation.MeansOfTransport;

public interface Airplane extends MeansOfTransport {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.agileactors.abstractfactory.meansoftransportation.airplane;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Slf4j
public class PostwarAirplane implements Airplane {

private static final Double MAX_CARGO_LOAD = 12000.00;
private String name;

public void checkCargo(String cargo) {
log.info("Checking what is needed to load cargo of type {} into the postwar airplane", cargo);
}

public void loadCargo(Double quantity) {
if (quantity.compareTo(MAX_CARGO_LOAD) > 0) {
log.info("Loaded cargo with quantity {} into several flights to be transported.", quantity);
} else {
log.info("Loaded cargo with quantity {} into one flight.", quantity);
}
}

public void sendToDestination(String destination) {
log.info("Sending cargo to destination {}", destination);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.agileactors.abstractfactory.meansoftransportation.airplane;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Slf4j
public class PrewarAirplane implements Airplane {

private static final Double MAX_CARGO_LOAD = 6000.00;
private String name;

public void checkCargo(String cargo) {
log.info("Checking what is needed to load cargo of type {} into the prewar airplane", cargo);
}

public void loadCargo(Double quantity) {
if (quantity.compareTo(MAX_CARGO_LOAD) > 0) {
log.info("Loaded cargo with quantity {} into several flights to be transported.", quantity);
} else {
log.info("Loaded cargo with quantity {} into one flight.", quantity);
}
}

public void sendToDestination(String destination) {
log.info("Sending cargo to destination {}", destination);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.agileactors.abstractfactory.meansoftransportation.ship;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Slf4j
public class PostwarShip implements Ship {

private static final Double MAX_CARGO_LOAD = 23000.00;
private String name;

public void checkCargo(String cargo) {
log.info("Checking what is needed to load cargo of type {} into the postwar ship", cargo);
}

public void loadCargo(Double quantity) {
if (quantity.compareTo(MAX_CARGO_LOAD) > 0) {
log.info("Loaded cargo with quantity {} into several postwar ships to be transported.",
quantity);
} else {
log.info("Loaded cargo with quantity {} into one postwar ship.", quantity);
}
}

public void sendToDestination(String destination) {
log.info("Sending cargo to port {}", destination);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.agileactors.abstractfactory.meansoftransportation.ship;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Slf4j
public class PrewarShip implements Ship {

private static final Double MAX_CARGO_LOAD = 13000.00;
private String name;

public void checkCargo(String cargo) {
log.info("Checking what is needed to load cargo of type {} into the prewar ship", cargo);
}

public void loadCargo(Double quantity) {
if (quantity.compareTo(MAX_CARGO_LOAD) > 0) {
log.info("Loaded cargo with quantity {} into several prewar ships to be transported.",
quantity);
} else {
log.info("Loaded cargo with quantity {} into one prewar ship.", quantity);
}
}

public void sendToDestination(String destination) {
log.info("Sending cargo to port {}", destination);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.agileactors.abstractfactory.meansoftransportation.ship;

import com.agileactors.abstractfactory.meansoftransportation.MeansOfTransport;

public interface Ship extends MeansOfTransport {

}
Loading