34 people like it.

State Pattern

the interest rate is decided by the internal state: account balance

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
type AccountState = 
    | Overdrawn
    | Silver
    | Gold
[<Measure>] type USD
type Account<[<Measure>] 'u>() =
    let mutable balance = 0.0<_>   
    member this.State
        with get() = 
            match balance with
            | _ when balance <= 0.0<_> -> Overdrawn
            | _ when balance > 0.0<_> && balance < 10000.0<_> -> Silver
            | _ -> Gold
    member this.PayInterest() = 
        let interest = 
            match this.State with
                | Overdrawn -> 0.
                | Silver -> 0.01
                | Gold -> 0.02
        interest * balance
    member this.Deposit(x:float<_>) =  
        let (a:float<_>) = x
        balance <- balance + a
    member this.Withdraw(x:float<_>) = balance <- balance - x

let state() = 
    let account = Account()

    account.Deposit(10000.<USD>)
    printfn "interest = %A" (account.PayInterest())

    account.Withdraw(20000.<USD>)
    printfn "interest = %A" (account.PayInterest())
union case AccountState.Overdrawn: AccountState
union case AccountState.Silver: AccountState
union case AccountState.Gold: AccountState
Multiple items
type MeasureAttribute =
  inherit Attribute
  new : unit -> MeasureAttribute

Full name: Microsoft.FSharp.Core.MeasureAttribute

--------------------
new : unit -> MeasureAttribute
[<Measure>]
type USD

Full name: Script.USD
Multiple items
type Account<'u> =
  new : unit -> Account<'u>
  member Deposit : x:float<USD> -> unit
  member PayInterest : unit -> float<USD>
  member Withdraw : x:float<USD> -> unit
  member State : AccountState

Full name: Script.Account<_>

--------------------
new : unit -> Account<'u>
val mutable balance : float<USD>
val this : Account<'u>
member Account.State : AccountState

Full name: Script.Account.State
member Account.PayInterest : unit -> float<USD>

Full name: Script.Account.PayInterest
val interest : float
property Account.State: AccountState
member Account.Deposit : x:float<USD> -> unit

Full name: Script.Account.Deposit
val x : float<USD>
Multiple items
val float : value:'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------
type float = System.Double

Full name: Microsoft.FSharp.Core.float

--------------------
type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>
val a : float<USD>
member Account.Withdraw : x:float<USD> -> unit

Full name: Script.Account.Withdraw
val state : unit -> unit

Full name: Script.state
val account : Account<1>
member Account.Deposit : x:float<USD> -> unit
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
member Account.PayInterest : unit -> float<USD>
member Account.Withdraw : x:float<USD> -> unit
Raw view Test code New version

More information

Link:http://fssnip.net/7l
Posted:13 years ago
Author:Tao Liu
Tags: design patterns