Scala builder pattern with abstract members
// It differs by (1) using abstract members and type members instead of parameters and type parameters and (2) contains visibility annotations.
1 2 object BuilderPattern { 3 sealed abstract class Preparation 4 case object Neat extends Preparation 5 case object OnTheRocks extends Preparation 6 case object WithWater extends Preparation 7 8 sealed abstract class Glass 9 case object Short extends Glass 10 case object Tall extends Glass 11 case object Tulip extends Glass 12 13 case class OrderOfScotch private[BuilderPattern] (val brand:String, val mode:Preparation, val isDouble:Boolean, val glass:Option[Glass]) 14 15 abstract class TRUE 16 abstract class FALSE 17 18 abstract class ScotchBuilder { self:ScotchBuilder => 19 protected[BuilderPattern] val theBrand:Option[String] 20 protected[BuilderPattern] val theMode:Option[Preparation] 21 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] 22 protected[BuilderPattern] val theGlass:Option[Glass] 23 24 type HAS_BRAND 25 type HAS_MODE 26 type HAS_DOUBLE_STATUS 27 28 def withBrand(b:String) = new ScotchBuilder { 29 protected[BuilderPattern] val theBrand:Option[String] = Some(b) 30 protected[BuilderPattern] val theMode:Option[Preparation] = self.theMode 31 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] = self.theDoubleStatus 32 protected[BuilderPattern] val theGlass:Option[Glass] = self.theGlass 33 34 type HAS_BRAND = TRUE 35 type HAS_MODE = self.HAS_MODE 36 type HAS_DOUBLE_STATUS = self.HAS_DOUBLE_STATUS 37 } 38 39 def withMode(p:Preparation) = new ScotchBuilder { 40 protected[BuilderPattern] val theBrand:Option[String] = self.theBrand 41 protected[BuilderPattern] val theMode:Option[Preparation] = Some(p) 42 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] = self.theDoubleStatus 43 protected[BuilderPattern] val theGlass:Option[Glass] = self.theGlass 44 45 type HAS_BRAND = self.HAS_BRAND 46 type HAS_MODE = TRUE 47 type HAS_DOUBLE_STATUS = self.HAS_DOUBLE_STATUS 48 } 49 50 51 def isDouble(b:Boolean) = new ScotchBuilder { 52 protected[BuilderPattern] val theBrand:Option[String] = self.theBrand 53 protected[BuilderPattern] val theMode:Option[Preparation] = self.theMode 54 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] = Some(b) 55 protected[BuilderPattern] val theGlass:Option[Glass] = self.theGlass 56 57 type HAS_BRAND = self.HAS_BRAND 58 type HAS_MODE = self.HAS_MODE 59 type HAS_DOUBLE_STATUS = TRUE 60 } 61 62 def withGlass(g:Glass) = new ScotchBuilder { 63 protected[BuilderPattern] val theBrand:Option[String] = self.theBrand 64 protected[BuilderPattern] val theMode:Option[Preparation] = self.theMode 65 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] = self.theDoubleStatus 66 protected[BuilderPattern] val theGlass:Option[Glass] = Some(g) 67 68 type HAS_BRAND = self.HAS_BRAND 69 type HAS_MODE = self.HAS_MODE 70 type HAS_DOUBLE_STATUS = self.HAS_DOUBLE_STATUS 71 } 72 73 } 74 75 type CompleteBuilder = ScotchBuilder { 76 type HAS_BRAND = TRUE 77 type HAS_MODE = TRUE 78 type HAS_DOUBLE_STATUS = TRUE 79 } 80 81 implicit def enableBuild(builder:CompleteBuilder) = new { 82 def build() = 83 new OrderOfScotch(builder.theBrand.get, builder.theMode.get, builder.theDoubleStatus.get, builder.theGlass); 84 } 85 86 def builder = new ScotchBuilder { 87 protected[BuilderPattern] val theBrand:Option[String] = None 88 protected[BuilderPattern] val theMode:Option[Preparation] = None 89 protected[BuilderPattern] val theDoubleStatus:Option[Boolean] = None 90 protected[BuilderPattern] val theGlass:Option[Glass] = None 91 92 type HAS_BRAND = FALSE 93 type HAS_MODE = FALSE 94 type HAS_DOUBLE_STATUS = FALSE 95 } 96 }