\ Preprocessor FOOS strategy pattern demo - Copyright 2016, 2022 J.L. Bezemer
\ You can redistribute this file and/or modify it under
\ the terms of the GNU General Public License

\ Translation of https://en.wikipedia.org/wiki/Strategy_pattern

include lib/memcell.4th
include lib/constant.4th
include 4pp/lib/foos.4pp

\ Encapsulated family of Algorithms
\ Interface and its implementations

:class IBrakeBehavior
   extends Object
     virtual: brake
   end-extends
;class

:class BrakeWithABS
   extends IBrakeBehavior
   end-extends

   :virtual brake ." Brake with ABS applied" ;method
;class

:class BrakeWithoutABS
   extends IBrakeBehavior
   end-extends

   :virtual brake ." Simple Brake applied" ;method
;class

\ Client that can use the algorithms above interchangeably

:class Car
   extends Object
     field:   brakeBehavior
     virtual: applyBrake
     virtual: setBrakeBehavior
   end-extends

   :new NULL this -> brakeBehavior ! ;method

   :virtual setBrakeBehavior
     this -> brakeBehavior @ NULL =
     unless this -> brakeBehavior @ delete then
     this -> brakeBehavior !
   ;method

   :virtual applyBrake this -> brakeBehavior @ => brake ;method
   :delete this -> brakeBehavior @ delete ;method
;class

\ Client 1 uses one algorithm (BrakeWithoutABS) in the constructor
:class Sedan
   extends Car
   end-extends

   :new new BrakeWithoutABS this -> brakeBehavior ! ;method
;class

\ Client 2 uses another algorithm (BrakeWithABS) in the constructor
:class SUV
   extends Car
   end-extends

   :new new BrakeWithABS this -> brakeBehavior ! ;method
;class

\ Using the Car example

: CarExample
  new Sedan value sedanCar
  sedanCar => applyBrake cr

  new SUV value suvCar
  suvCar => applyBrake cr
                                       \ set brake behavior dynamically
  new BrakeWithoutABS suvCar => setBrakeBehavior
  suvCar => applyBrake cr

  sedanCar delete
  suvCar   delete
;

CarExample
