;We start with a basic in-memory implementation: (defprotocol DataProvider ;We pass the instance to the functions as "this" (the name is arbitrary) (find-user [this id])) (deftype MemoryDataProvider [] DataProvider (find-user [this id] (first (filter #(= (:id %) id) [ {:id 1 :name "betty"} {:id 2 :name "mike"}])))) ;Test: create an instance and find user with id 2 (def my-data-provider (MemoryDataProvider.)) (find-user my-data-provider 2) ;In the database implementation we need to pass e.g. host and port ;in order to establish a connection. We do this using the constructor ;function of the type (see DBDataProvider below). ;We also need to add a function to establish the connection. We have to ;do add it also to the protocol, since the client has to call it and doesn't know ;the implementation. We add a generic method "init" to the protocol, ;for this purpose. ;(Note that "init" means side effects, so this doesn't really make ;sense in the in-memory implementation, but don't see a better solution). (defprotocol DataProvider (init [this]) (find-user [this id])) ;We have to add the method to MemoryDataProvider. Not doing this will ;not cause compiler error, but will throw runtime error if init is ;called on this type (deftype MemoryDataProvider [] DataProvider (init [this]) (find-user [this id] (first (filter #(= (:id %) id) [ {:id 1 :name "betty"} {:id 2 :name "mike"}])))) ;Test (def my-data-provider (MemoryDataProvider.)) (init my-data-provider) ;nil (find-user my-data-provider 2) ;This is the database data provider type (deftype DBDataProvider [host port] DataProvider (init [this] (println "host: " host ", port: " port) ;connect... ) (find-user [this id] ;get it from database... {:id 0 :name "test"} ) ) (def my-data-provider (DBDataProvider. "127.0.0.1" "1234")) (init my-data-provider) ;nil (find-user my-data-provider 2) ;We can also make init return the type: (deftype DBDataProvider [host port] DataProvider (init [this] (println "host: " host ", port: " port) ;connect... this ) (find-user [this id] ;get it from database... {:id 0 :name "test"} ) ) ;then we can do: (def my-data-provider (init (DBDataProvider. "127.0.0.1" "1234"))) (find-user my-data-provider 2)
Note: I'm new to Clojure, glad to receive corrections or suggestions in the case something can be improved.
These snippets can be found (together with others) here.
No comments:
Post a Comment