Loan Pattern as the name suggests would loan a resource to your function. So if you break out the sentence. It would
就像名字所说的一样,贷出模式(Loan Pattern)会借贷出一个资源给予你的函数。它可以 1.创建一个你可以使用的资源 2.载入这个资源到你的函数中让你使用 3.函数由调用者提供 4.资源会被摧毁回收
As you would see, the advantages are multifold. First, I am not constrained by the function which can use the loaned resource. I can pass any function that I desire. Second, I am not concerned about the creation, destruction of the resource. The loan function takes care of it.
就像你即将看到的一样,贷出模式的优势有很多。首先我不会受到使用资源的函数的限制。我可以传入我希望的任何函数。 第二个优势是我不用担心资源的创建和回收。贷出函数会自己处理这些。
Let us take an example, we have all used connections to get to the database and then we need to destroy the connection so that there are no leaks. OK, we can use the connection factory but let us assume that we do not have that for now. The general code would look like this
让我们举一个例子,我们都使用过数据库连接并用它连接数据库,再回收数据库连接以确保没有资源泄露。当然,我们可以使用数据库连接的工厂类,但是假设我们现在没有工厂类。那么代码就大概像下面这样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def
doSqlCall
=
{
var
conn
:
Connection
=
null
try
{
val
url
=
"jdbc:mysql://localhost:3306/"
Class.forName(
"com.mysql.jdbc.Driver"
).newInstance()
conn
=
DriverManager.getConnection(url +
"vikas"
,
"userName"
,
"password"
)
val
stmt
=
conn.prepareStatement(
"insert into employee (id,age) values (?,?) "
)
stmt.setString(
1
,
"1001"
)
stmt.setInt(
2
,
"21"
)
stmt.executeUpdate
}
catch
{
case
ex
:
Exception
=
> {
println(
"Exception: "
+ ex.getMessage)
}
}
finally
{
conn.close
}
}
|
As you would notice that the code snippet can be improved for confirming to the functional standards but that is not the motive right now. If you notice, apart from all the boilerplating or all the work that needs to be done, a few lines are all that change everytime this function is called.
你会注意到这段代码中大部分代码都是用来建立或回收数据库连接,类似于一个“模板”,只有一小段代码是有可能发生变化的,就是下面这一段。
1
2
3
4
|
val
stmt
=
conn.prepareStatement(
"insert into employee (id,age) values (?,?) "
)
stmt.setString(
1
,
"1001"
)
stmt.setInt(
2
,
"21"
)
stmt.executeUpdate
|
What if we could pass these 4 lines to the function above and still be able to use the boilerplating. The loan pattern attempts to provide exactly that. You would need to pass the functionality and not worry about the resources.
如果我们把这四句代码放入一个函数,并且仍然可以使用那个创建/回收数据库连接的“模板”,那感觉如何呢?这就是贷出模式要做的。你只需要传入一个自定义函数(类似于上面这四句代码),而不需要担心资源的创建和回收。
Let us pull the code that we want to execute into a method of its own
让我们把我们希望执行的代码(上面四句)提取出来放入一个单独的函数
1
2
3
4
5
6
|
def
executeMySqlFunction(conn
:
Connection)
:
Int
=
{
val
stmt
=
conn.prepareStatement(
"insert into employee (id,age) values (?,?) "
)
stmt.setString(
1
,
"1001"
)
stmt.setInt(
2
,
"21"
)
stmt.executeUpdate
}
|
You would see that this method takes connection (which is the resource which would be loaned) as an argument and returns integer.
你回看到这个方法需要数据库连接(会被使用的资源)作为参数,并返回一个整型值
Now let us look at the base method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
def
doLoanSqlCall(f
:
Connection
=
>Int)
=
{
var
conn
:
Connection
=
null
try
{
val
url
=
"jdbc:mysql://localhost:3306/"
Class.forName(
"com.mysql.jdbc.Driver"
).newInstance()
conn
=
DriverManager.getConnection(url +
"vikas"
,
"userName"
,
"password"
)
f(conn)
}
catch
{
case
ex
:
Exception
=
> {
println(
"Exception: "
+ ex.getMessage)
}
}
finally
{
conn.close
}
}
|
Here, we have defined the doLoanSqlCall as a method, which would take another function as an argument. Thus, doLoanSqlCall becomes a higher order function. The function which is taken as an argument should take a connection as an argument and return Int. If you look at the definition of
这里,我们已经定义了一个函数 doLoadSqlCall(),它会将另一个函数(我们就称它为用户函数)作为参数。因此,doLoadSqlCall()变成了一个更高阶的函数。作为参数的函数(用户函数)应该将数据库连接作为参数,并返回一个整型值。如果你看下用户函数的定义:
1
|
def
executeMySqlFunction(conn
:
Connection)
:
Int
|
it does exactly that. Takes connection as the argument and returns an Int. The only thing that executeMySqlFunction does not have to worry about is that how would be create the connection and whether it needs to destroy the connection when it is done. The connection resource is loaned by the other method.
Hence the call becomes
1
|
doLoanSqlCall(executeMySqlFunction)
|
and this is now valid for any other SQL function which follows the format connection=>Int
感受与总结:贷出模式就是一个将需要系统资源执行的操作抽象的模式。本来的逻辑是:1. 创建系统资源 2.执行用户需要的逻辑 3.回收系统资源。但是如果使用了贷出模式,那么就被抽象成为了两个函数:1)用户函数 和 2)贷出函数。用户函数作为参数传入给贷出函数。调用者需要调用的是 贷出函数。
1)用户函数(user_function)中定义了用户自己希望执行的操作(这些操作需要使用系统资源)。由于这些操作需要使用系统资源,那么资源会作为用户函数的参数传入,以提供给用户使用。
2)贷出函数(load_function)中则定义了系统资源的获取与回收,并且在获取资源之后,回收资源之前,调用用户函数(将系统资源作为参数传入)。
结构类似于:
load_function(user_function) { allocate resource user_function(resource) release resource}
终端用户需要直接调用的是贷出函数。