看开源的源代码,看到一个有意思的实现 。
/*
* 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 接口定义 的方法,这里是其实现
public CommitHandler create(String transactionId, Network network) {
return factory.create(transactionId, network);
}
}
先看看enum类的构造函数
DefaultCommitHandlers(CommitHandlerFactory factory) {
this.factory = factory;
}
需要一个 CommitHandlerFactory 是个接口,同时 enum类本身也实现了这个接口。
再来看调用过程
CommitHandlerFactory commitHandlerFactory = DefaultCommitHandlers.MSPID_SCOPE_ALLFORTX;
这里会调用CommitHandlerFactory 构造函数,其传入参数是
(transactionId, network) -> {
Collection<Peer> peers = network.getChannel().getPeers();
CommitStrategy strategy = new AllCommitStrategy(peers);
CommitHandler handler = new CommitHandlerImpl(transactionId, network, strategy);
return handler;
}
它是lamdba写法,看看构造函数需要一个 CommitHandlerFactory 接口,这个lamdba 函数其实就是CommitHandlerFactory 的实现。
这样MSPID_SCOPE_ALLFORTX 枚举类型就有了一个 CommitHandlerFactory实现类的引用。
再看create调用。
CommitHandler commitHandler = commitHandlerFactory.create(transactionId, network);
这里enum类的create方法会执行, return factory.create(transactionId, network);
返回一个 CommitHandler .这里才会真正执行那个 lamdba定义的函数。
到这里只看到lamdb应用。。。
再分析一下create ,枚举类里的每个枚举变量都会实现一个这个方法。这里可以看到它其实是一个工厂类。
它创造的产品是CommitHandler ,其具体实现是CommitHandlerImpl类。
这里巧妙的使用一个enum当工厂类的实现。整个代码用了工厂模式加策略模式的实现。
优点:得宜于lamdb的应用,减少了具体工厂类的实现。
缺点:工厂模式可以实现不改动程序创建产品。那么这里如果要增一个产品,对这个enum类需要再添加一个枚举变量。
这个enum类有改动。