joesan
joesan

Reputation: 15435

Scala design suggestion needed

I would like to design a client that would talk to a REST API. I have implemented the bit that actually does call the HTTP methods on the server. I call this Layer, the API layer. Each operation the server exposes is encapsulated as one method in this layer. This method takes as input a ClientContext which contains all the needed information to make the HTTP method call on the server.

I'm now trying to set up the interface to this layer, let's call it ClientLayer. This interface will be the one any users of my client library should use to consume the services. When calling the interface, the user should create the ClientContext, set up the request parameters depending on the operation that he is willing to invoke. With the traditional Java approach, I would have a state on my ClientLayer object which represents the ClientContext:

For example:

public class ClientLayer {
 private static final ClientContext;
 ...
} 

I would then have some constructors that would set up my ClientContext. A sample call would look like below:

ClientLayer client = ClientLayer.getDefaultClient();
client.executeMyMethod(client.getClientContext, new MyMethodParameters(...))

Coming to Scala, any suggestions on how to have the same level of simplicity with respect to the ClientContext instantiation while avoiding having it as a state on the ClientLayer?

Upvotes: 1

Views: 70

Answers (1)

tuxdna
tuxdna

Reputation: 8487

I would use factory pattern here:

object RestClient {
  class ClientContext
  class MyMethodParameters

  trait Client {
    def operation1(params: MyMethodParameters)
  }

  class MyClient(val context: ClientContext) extends Client {
    def operation1(params: MyMethodParameters) = {
      // do something here based on the context
    }
  }

  object ClientFactory {
    val defaultContext: ClientContext = // set it up here;

    def build(context: ClientContext): Client = {
      // builder logic here
      // object caching can be used to avoid instantiation of duplicate objects 
      context match {
        case _ => new MyClient(context)
      }
    }

    def getDefaultClient = build(defaultContext)

  }

  def main(args: Array[String]) {
    val client = ClientFactory.getDefaultClient
    client.operation1(new MyMethodParameters())
  }

}

Upvotes: 1

Related Questions