;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