Skip to content

Instantly share code, notes, and snippets.

@devsdmf
Last active February 13, 2020 20:06
Show Gist options
  • Save devsdmf/66c5988f2b3474fa06b5142897db1651 to your computer and use it in GitHub Desktop.
Save devsdmf/66c5988f2b3474fa06b5142897db1651 to your computer and use it in GitHub Desktop.
Scala's Adapters and Strategies
// DEFINITIONS
trait DiscountCode {
def getValue: Double
}
trait Adapter[E] {
def updateAndReturnEntity(entity: E, amount: Double): E
def toValue(entity: E): Double
}
trait Strategy {
def calculate(amount: Double, discountCode: DiscountCode): Double
}
trait Calculator [E] {
def applyDiscount(entity: E, discountCode: DiscountCode): E
}
// CONCRETIONS
// DiscountCode entity
case class BaseDiscountCode(id: Int, value: Double) extends DiscountCode {
def getValue: Double = this.value
}
// Order and TicketType entities
case class Order(id: Int, totalSalePrice: Double) {
// using copy because case classes are immutable
def updateTotalSalePrice(amount: Double): Order = copy(totalSalePrice = amount)
}
case class TicketType(id: Int, salePrice: Double) {
// using copy because case classes are immutable
def updateSalePrice(amount: Double): TicketType = copy(salePrice = amount)
}
// context adapters
class OrderBasedAdapter extends Adapter[Order] {
def updateAndReturnEntity(entity: Order, amount: Double): Order = {
// performs calculations
entity.updateTotalSalePrice(amount)
}
def toValue(entity: Order): Double = entity.totalSalePrice
}
class TicketTypeBasedAdapter extends Adapter[TicketType] {
def updateAndReturnEntity(entity: TicketType, amount: Double): TicketType = {
// performs calculations
entity.updateSalePrice(amount)
}
def toValue(entity: TicketType): Double = entity.salePrice
}
// The strategy
class FixedValueStrategy extends Strategy {
def calculate(amount: Double, discountCode: DiscountCode): Double = amount - discountCode.getValue
}
// The calculator
case class DiscountCodeCalculator[E, A <: Adapter[E]](adapter: A, strategy: Strategy) extends Calculator[E] {
def applyDiscount(entity: E, discountCode: DiscountCode): E =
adapter.updateAndReturnEntity(entity,strategy.calculate(adapter.toValue(entity),discountCode))
}
// USAGE
object Main extends App {
// given a discount code
val discountCode = new BaseDiscountCode(1,10.0)
// with strategy...
val strategy = new FixedValueStrategy
// calculating for TicketType...
val ticket = new TicketType(1,100.0)
// with adapter...
val tAdapter = new TicketTypeBasedAdapter
// with calculator...
val tCalculator = new DiscountCodeCalculator[TicketType,TicketTypeBasedAdapter](tAdapter,strategy)
// and calculate!
val updatedTicketType = tCalculator.applyDiscount(ticket,discountCode)
println(ticket)
println(updatedTicketType)
// calculating for Order...
val order = new Order(1,200.00)
// with adapter...
val oAdapter = new OrderBasedAdapter
// with calculator...
val oCalculator = new DiscountCodeCalculator[Order,OrderBasedAdapter](oAdapter,strategy)
// and calculate!
val updatedOrder = oCalculator.applyDiscount(order,discountCode)
println(order)
println(updatedOrder)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment