Мост
Немного повоевав с applicationContext получилось закодить паттерн Мост. Он позволяет связать 2 группы объектов, между которыми есть зависимость таким образом, чтобы при добавлении в эти группы новых сущностей не приходилось что-либо менять в коде. В примере ниже сделала 2 типа отчетов и 2 типа форматов файлов, в которые они генерируются. В чем красота: для добавления нового типа отчета - достаточно добавить класс, реализующий интерфейс Report. Для нового формата - интерфейс FileCreator. С чем пришлось повозиться: разобраться как при помощи applicationContext создавать прототипы, передавая при этом в них параметры. Хотела через ObjectProvider<T> это сделать, а вот фигушки...
interface Report {
fun saveToFile(path: String, creator: FileCreator)
}
@Component
@Scope("prototype")
class SalaryReport(val rawData: String) : Report {
override fun saveToFile(path: String, creator: FileCreator) =
creator.create("Salary header. $rawData", path)
}
@Component
@Scope("prototype")
class EmployeeReport(val rawData: String) : Report {
override fun saveToFile(path: String, creator: FileCreator) =
creator.create("Employee header. $rawData", path)
}
interface FileCreator {
fun create(rawData: String, path: String)
}
@Component
class PdfFileCreator : FileCreator {
override fun create(rawData: String, path: String) {
println("Сохранение файла $path.pdf. Данные: $rawData")
}
}
@Component
class DocxFileCreator : FileCreator{
override fun create(rawData: String, path: String) {
println("Сохранение файла $path.docx. Данные: $rawData")
}
}
@RestController
class ReportCreatorController (
val creators: Map<String, FileCreator>,
val applicationContext: ApplicationContext
) {
@GetMapping
fun create(
@RequestParam reportType: String,
@RequestParam creatorType: String,
@RequestParam rawData: String,
@RequestParam path: String,
) {
val report = applicationContext.getBean(reportType, rawData) as Report
report.let {
creators[creatorType]?.let { creator ->
report.saveToFile(path, creator)
}
}
}
}
Фсё хочу спросить.
Ты шо там ваще делаишь?
Пытаюсь все паттерны на связке Котлин + Спринг написать. Заодно и язык и фреймворк изучаю
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.annotation.Scope
import org.springframework.stereotype.Component
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
// Enum для типов отчетов
enum class ReportType {
SALARY, EMPLOYEE
}
// Enum для форматов файлов
enum class FileFormat {
PDF, DOCX
}
// Интерфейс отчетов
interface Report {
fun saveToFile(path: String, creator: FileCreator)
}
// Отчёт о зарплате
@Component
@Scope("prototype")
class SalaryReport(private val rawData: String) : Report {
override fun saveToFile(path: String, creator: FileCreator) {
creator.create("Salary header. $rawData", path)
}
}
// Отчёт о сотрудниках
@Component
@Scope("prototype")
class EmployeeReport(private val rawData: String) : Report {
override fun saveToFile(path: String, creator: FileCreator) {
creator.create("Employee header. $rawData", path)
}
}
// Интерфейс создателей файлов
interface FileCreator {
fun create(rawData: String, path: String)
}
// Создатель PDF-файлов
@Component
class PdfFileCreator : FileCreator {
private val logger: Logger = LoggerFactory.getLogger(PdfFileCreator::class.java)
override fun create(rawData: String, path: String) {
logger.info("Сохранение файла $path.pdf. Данные: $rawData")
}
}
// Создатель DOCX-файлов
@Component
class DocxFileCreator : FileCreator {
private val logger: Logger = LoggerFactory.getLogger(DocxFileCreator::class.java)
override fun create(rawData: String, path: String) {
logger.info("Сохранение файла $path.docx. Данные: $rawData")
}
}
// Фабрика отчетов
@Component
class ReportFactory {
fun createReport(type: ReportType, rawData: String): Report {
return when (type) {
ReportType.SALARY -> SalaryReport(rawData)
ReportType.EMPLOYEE -> EmployeeReport(rawData)
}
}
}
// Фабрика создателей файлов
@Component
class FileCreatorFactory(
private val pdfCreator: PdfFileCreator,
private val docxCreator: DocxFileCreator
) {
fun getCreator(format: FileFormat): FileCreator {
return when (format) {
FileFormat.PDF -> pdfCreator
FileFormat.DOCX -> docxCreator
}
}
}
// Сервис для генерации отчетов
@Component
class ReportService(
private val reportFactory: ReportFactory,
private val fileCreatorFactory: FileCreatorFactory
) {
private val logger: Logger = LoggerFactory.getLogger(ReportService::class.java)
fun generateReport(reportType: ReportType, fileFormat: FileFormat, rawData: String, path: String) {
val report = reportFactory.createReport(reportType, rawData)
val creator = fileCreatorFactory.getCreator(fileFormat)
logger.info("Генерация отчета типа $reportType в формате $fileFormat")
report.saveToFile(path, creator)
}
}
// Контроллер
@RestController
class ReportController(private val reportService: ReportService) {
@GetMapping("/create-report")
fun createReport(
@RequestParam reportType: ReportType,
@RequestParam fileFormat: FileFormat,
@RequestParam rawData: String,
@RequestParam path: String
) {
reportService.generateReport(reportType, fileFormat, rawData, path)
}
}
вижу when в коде, а у меня его нет) Новые типы проще добавляются
Я ничего не понимаю 🧐
Для меня программеры это полубоги 🫣😳