Protocol + Client Namespace + Multimethod
You could use a protocol to define the abstraction, except connect, which is a multimethod:
1Â (ns stadig.storage.protocol 2Â Â Â (:refer-clojure :exclude [get])) 3 4Â (defprotocol IStorage 5Â Â Â (get [this bucket key]) 6Â Â Â (put [this bucket key value]) 7Â Â Â (delete [this bucket key]) 8Â Â Â (close [this])) 9 10Â (defmulti connect :backend)
Implement the protocol and multimethod for each backend:
1Â (ns stadig.storage.s3 2Â Â Â (:require 3Â Â Â Â [aws.sdk.s3 :as s3] 4Â Â Â Â [stadig.storage.protocol :as proto])) 5 6Â (defrecord S3Storage 7Â Â Â Â Â [access-key secret-key] 8Â Â Â proto/IStorage 9Â Â Â (get [this bucket key] 10Â Â Â Â Â (s3/get-object this bucket key)) 11Â Â Â (put [this bucket key value] 12Â Â Â Â ...