看開源的源代碼,看到一個有意思的實現(xiàn) 。
/*
* Copyright 2019 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.fabric.gateway;
import org.hyperledger.fabric.gateway.impl.AllCommitStrategy;
import org.hyperledger.fabric.gateway.impl.AnyCommitStrategy;
import org.hyperledger.fabric.gateway.impl.CommitHandlerImpl;
import org.hyperledger.fabric.gateway.impl.CommitStrategy;
import org.hyperledger.fabric.gateway.impl.NoOpCommitHandler;
import org.hyperledger.fabric.gateway.spi.CommitHandler;
import org.hyperledger.fabric.gateway.spi.CommitHandlerFactory;
import org.hyperledger.fabric.sdk.Peer;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import java.util.Collection;
/**
* Default commit handler implementations. Instances can be referenced directly or looked up by name, for example
* {@code DefaultCommitHandlers.valueOf("NONE")}.
*/
public enum DefaultCommitHandlers implements CommitHandlerFactory {
/**
* Do not wait for any commit events to be received from peers after submitting a transaction.
*/
NONE((transactionId, network) -> NoOpCommitHandler.INSTANCE),
/**
* Wait to receive commit events from all currently responding peers in the user's organization after submitting
* a transaction.
*/
MSPID_SCOPE_ALLFORTX((transactionId, network) -> {
Collection<Peer> peers = getPeersForOrganization(network);
CommitStrategy strategy = new AllCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
}),
/**
* Wait to receive commit events from all currently responding peers in the network after submitting a transaction.
*/
NETWORK_SCOPE_ALLFORTX((transactionId, network) -> {
Collection<Peer> peers = network.getChannel().getPeers();
CommitStrategy strategy = new AllCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
}),
/**
* Wait to receive a commit event from any currently responding peer in the user's organization after submitting
* a transaction.
*/
MSPID_SCOPE_ANYFORTX((transactionId, network) -> {
Collection<Peer> peers = getPeersForOrganization(network);
CommitStrategy strategy = new AnyCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
}),
/**
* Wait to receive a commit event from any currently responding peer in the network after submitting a transaction.
*/
NETWORK_SCOPE_ANYFORTX((transactionId, network) -> {
Collection<Peer> peers = network.getChannel().getPeers();
CommitStrategy strategy = new AnyCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
});
private final CommitHandlerFactory factory;
DefaultCommitHandlers(CommitHandlerFactory factory) {
this.factory = factory;
}
private static Collection<Peer> getPeersForOrganization(Network network) {
String mspId = network.getGateway().getIdentity().getMspId();
try {
return network.getChannel().getPeersForOrganization(mspId);
} catch (InvalidArgumentException e) {
// This should never happen as mspId should not be null
throw new RuntimeException(e);
}
}
//CommitHandlerFactory 接口定義 的方法,這里是其實現(xiàn)
public CommitHandler create(String transactionId, Network network) {
return factory.create(transactionId, network);
}
}
先看看enum類的構(gòu)造函數(shù)
DefaultCommitHandlers(CommitHandlerFactory factory) {
this.factory = factory;
}
需要一個 CommitHandlerFactory 是個接口,同時 enum類本身也實現(xiàn)了這個接口。
再來看調(diào)用過程
CommitHandlerFactory commitHandlerFactory = DefaultCommitHandlers.MSPID_SCOPE_ALLFORTX;
這里會調(diào)用CommitHandlerFactory 構(gòu)造函數(shù),其傳入?yún)?shù)是
(transactionId, network) -> {
Collection<Peer> peers = network.getChannel().getPeers();
CommitStrategy strategy = new AllCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
}
它是lamdba寫法,看看構(gòu)造函數(shù)需要一個 CommitHandlerFactory 接口,這個lamdba 函數(shù)其實就是CommitHandlerFactory 的實現(xiàn)。
這樣MSPID_SCOPE_ALLFORTX 枚舉類型就有了一個 CommitHandlerFactory實現(xiàn)類的引用。
再看create調(diào)用。
CommitHandler commitHandler = commitHandlerFactory.create(transactionId, network);
這里enum類的create方法會執(zhí)行, return factory.create(transactionId, network);
返回一個 CommitHandler .這里才會真正執(zhí)行那個 lamdba定義的函數(shù)。
到這里只看到lamdb應(yīng)用。。。
再分析一下create ,枚舉類里的每個枚舉變量都會實現(xiàn)一個這個方法。這里可以看到它其實是一個工廠類。
它創(chuàng)造的產(chǎn)品是CommitHandler ,其具體實現(xiàn)是CommitHandlerImpl類。
這里巧妙的使用一個enum當(dāng)工廠類的實現(xiàn)。整個代碼用了工廠模式加策略模式的實現(xiàn)。
優(yōu)點:得宜于lamdb的應(yīng)用,減少了具體工廠類的實現(xiàn)。
缺點:工廠模式可以實現(xiàn)不改動程序創(chuàng)建產(chǎn)品。那么這里如果要增一個產(chǎn)品,對這個enum類需要再添加一個枚舉變量。
這個enum類有改動。