Pular para o conteúdo
Bruno Dórea
Todos os posts

7 mins de leitura


Builder - Construindo um Pedido Personalizado

Explorando Padrões de Projetos com Kotlin - 2/5


Desenvolvimento Backend com Kotlin
Desenvolvimento Backend com Kotlin

Descrição

O Design Pattern "Builder" é uma técnica utilizada para criar objetos complexos passo a passo, separando o processo de construção da representação final do objeto. Isso ajuda a melhorar a legibilidade e a flexibilidade do código, especialmente quando você precisa criar objetos com muitos parâmetros ou configurações diferentes.

Neste desafio, buscando soluções para um problema de negócios em uma plataforma de e-commerce, é necessário melhorar a forma como os pedidos personalizados são tratados. Você tem a opção de implementar a solução utilizando o padrão Builder para criar pedidos de forma mais eficiente e organizada, ou seguir uma abordagem alternativa sem a necessidade de utilizar o padrão Builder.

Detalhamento da tarefa:

  • Capture o nome do cliente.
  • Solicite ao usuário a quantidade de produtos que deseja adicionar ao pedido.
  • Para cada produto, capture o nome, preço e quantidade.
  • Capture o endereço de entrega.
  • Calcule o total do pedido somando o preço de cada produto multiplicado pela quantidade.
  • Imprima os detalhes do pedido, incluindo os produtos, seus preços, quantidades, total a pagar e endereço de entrega.

Entrada

O programa deve receber as seguintes informações do usuário:

  • Nome do cliente (string);
  • Lista de produtos a serem incluídos no pedido (cada produto possui nome, preço e quantidade);
  • Endereço de entrega (string).

Saída

Após receber todas as informações do usuário, o programa deve criar um objeto de pedido personalizado usando o padrão Builder e imprimir os detalhes do pedido construído, incluindo o total a pagar.

Para este desafio, considere apenas uma casa decimal após a vírgula.

Exemplos

A tabela abaixo apresenta exemplos com alguns dados de entrada e suas respectivas saídas esperadas. Certifique-se de testar seu programa com esses exemplos e com outros casos possíveis.

EntradaSaída
Ada
1Ada
Chocolate1. Chocolate - 1.5 - 2 *
1.5Total: 3.0
3End: Arabaiana
Arabaiana
EntradaSaída
Dante
1Dante
Suco1. Suco - 2.5 - 2 *
2.5Total: 5.0
2End: Alto
Alto
EntradaSaída
Sofia
1Sofia
Pipoca1. Pipoca - 4.5 - 3 *
4.5Total: 13.50
3End: Lagoa
Lagoa
  • substitua o - por um pipe |

Nota

O padrão Builder é uma abordagem valiosa quando se trata de criar objetos complexos com diferentes configurações. No entanto, deve-se considerar a relação entre a complexidade do problema e a necessidade de aplicar o padrão, especialmente em cenários mais simples. A decisão de usar ou não o padrão Builder dependerá das necessidades específicas do projeto e das características do sistema em que está sendo aplicado.

Resolução

class Product(val name: String, val price: Double, val quantity: Int)
 
class CustomOrder private constructor(
    val customerName: String,
    val products: List<Product>,
    val total: Double,
    val deliveryAddress: String
) {
    class Builder {
        private var customerName: String = ""
        private var products: MutableList<Product> = mutableListOf()
        private var deliveryAddress: String = ""
 
        fun setCustomerName(name: String) = apply { customerName = name }
        fun addProduct(product: Product) = apply { products.add(product) }
        fun setDeliveryAddress(address: String) = apply { deliveryAddress = address }
 
        fun build(): CustomOrder {
            val total = products.sumOf { it.price * it.quantity }
            return CustomOrder(customerName, products, total, deliveryAddress)
        }
    }
 
    fun printReceipt() {
        println(customerName)
        products.forEachIndexed { index, product ->
            println("${index + 1}. ${product.name} | ${product.price} | ${product.quantity}")
        }
        println("Total: %.1f".format(total))
        println("End: $deliveryAddress")
    }
}
 
fun main() {
    val customerName = readLine() ?: ""
    val orderBuilder = CustomOrder.Builder().setCustomerName(customerName)
 
    val numProducts = readLine()?.toIntOrNull() ?: 0
    for (i in 1..numProducts) {
        val productName = readLine() ?: ""
        val productPrice = readLine()?.toDoubleOrNull() ?: 0.0
        val productQuantity = readLine()?.toIntOrNull() ?: 0
        orderBuilder.addProduct(Product(productName, productPrice, productQuantity))
    }
 
    val deliveryAddress = readLine() ?: ""
    val customOrder = orderBuilder.setDeliveryAddress(deliveryAddress).build()
 
    customOrder.printReceipt()
}

Para encontrar outras soluções, verifique aqui.

Caso encontre algum erro ou tenha sugestões, clique aqui e abra uma issue no Github.