Last active
February 13, 2020 20:06
-
-
Save devsdmf/66c5988f2b3474fa06b5142897db1651 to your computer and use it in GitHub Desktop.
Scala's Adapters and Strategies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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