将其转变为功能性方法的主要目的是计算一个新世界。在您的示例中,银行状态就是您的世界,因此您希望为每个 TX 计算一个新的银行状态。这可能看起来像:
class BankState implements Function<Id, AccountState> {
final Map<Id, AccountState> balances; // ctor injected immutable
/** initial ctor, build a map of balances computed by from function */
BankState(Function<Id, Option<AccountState>> from, Iterable<Id> accounts) {
this.balances = computeMap(from, accounts);//
}
/** overlay ctor, if account state provided by the tx use that,
* otherwise the old one is used */
BankState(Function<Id, Option<AccountState>> tx, Map<Id, AccountState> old) {
this.balances = overlay(tx, old);// special map with overlay
}
public AccountState apply(Id id) {return balances.get(id);}
public BankState update(Function<Id, Option<AccountState>> tx) {
return new BankState(tx, balances);
}
public BankState transfer(final Id from, final Id to, final Money amount) {
return update(new Function<Id, Option<AccountState>>() {
public Option<AccountState> apply(Id id) {
if (id.equals(from) return some(bank.apply(id).debit(amount));
if (id.equals(to) return some(bank.apply(id).credit(amount));
return none();
}
});
}
}
然后,您可以简单地使用 AtomicReference 来保存当前状态并以原子方式将其更新为新的 BankState。
您需要覆盖和计算地图实现,但这些很容易使用 Guava 创建(例如,它已经有 MapMaker.makeComputingMap(Function))。
出于说明目的,这是一个幼稚的实现,真正的实现将包含许多优化。
我使用的选项在这里:https ://bitbucket.org/atlassian/fugue/src/master/src/main/java/com/atlassian/fugue/Option.java