比方说,
class ClientFunc {
def client(s: String): Future[Service] = ....
def m1(s: String) = {
client(s).map( ...... )
}
...//there are multiple such methods like m1 in this class which
depends on "def client".
}
现在,我们必须再添加一个具有相同实现方式的相同类型的客户端,并根据需要将其与现有客户端一起使用。
因此,有两种方法可以解决此问题。 解决方案一:使用继承,就像使父客户端方法抽象一样,为两个不同的客户端提供子类classA和clientB作为实现。
class clientA extends ClientFunc {
def client(s: String): Future[Service] = ....
}
class clientB extends ClientFunc {
def client(s: String): Future[Service] = ....
}
照常使用
clientAInstance.m1("str")
and
clientBInstance.m1("str")
根据用例,我必须一次使用clientA和clientB,因此我需要在服务中注入两个客户端。
其他解决方案:通过使像函数“ def m1”一样高阶并在其中传递客户端,保持ClientFunc类不变,为其他客户端(如(def clientB))添加一个功能,
class ClientFunc {
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
def m1(s: String, cl:String => Future[Service]) = {
cl(s).map( ...... )
}
}
现在,无论何时我必须打电话,我都会像这样打电话
ClientFuncInstance.m1("str", ClientFuncInstance.clientA)
and
ClientFuncInstance.m1("str", ClientFuncInstance.clientB)
无需两次注入ClientFunc。
问题是Scala /函数式编程中哪一种是首选方式? &为什么?如果有其他更好的方法,请提出建议。
答案 0 :(得分:1)
我认为最好的方法是在构造函数中注入client
:
class ClientFunc(client: String => Future[Service]) {
def m1(s: String) = {
client(s).map( ...... )
}
...
}
您可以添加新的实现(包括用于测试的模拟),而无需更改现有代码。
[评论后更新]
您将像这样使用它:
def clientA(s: String): Future[Service] = ....
def clientB(s: String): Future[Service] = ....
val clientFuncA = new ClientFunc(clientA)
val clientFuncB = new ClientFunc(clientB)
class Service(funcA: ClientFunc, funcB: ClientFunc) {
def flag = ...
def client = if (flag) { funcA } else { funcB }
def m1(s: String) = {
client.m1(s)
}
}
val service = new Service(clientFuncA, clientFuncB)