自從 Java8 支持 lambda 表達式, 代碼中的 lambda 就到處都是。 但大多是濫用。
lambda 表達式用於表達簡短的邏輯(可以看做 C 語言的內聯函數)非常清晰,但用來表達比較長的業務邏輯,就與其設計初衷背道而馳了。
如下所示,三層嵌套 lambda 表達式,暈了沒有 ?
如何解開這些結呢 ? 一步步來。
首先, allImageIds.forEach 是一個明顯的 Stream-add 模式,可以使用 stream.map 來表達:
List<CompletableFuture<String>> completableFutureList
= allImageIds.stream().map(imageId -> buildCompletableFuture(imageId, comId, newGroup)).collect(Collectors.toList());
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, () -> {
return dealWith(comId, newGroup, imageId);
});
}, executorService);
return future;
}
這樣,就解耦了一層。
接下來,CompletableFuture.supplyAsync 需要提供一個 Supplier
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
Supplier<String> futureSupplier = () -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, () -> {
return dealWith(comId, newGroup, imageId);
});
};
CompletableFuture<String> future = CompletableFuture.supplyAsync(futureSupplier, executorService);
return future;
}
這樣,我們又讓結構清晰了一些。
最后,我們把 redisLock.call 里面的 lambda 表達式分離出來。 這個 lambda 表達式代表的是 ValueLockCallback 接口。 可以把這個表達式變成一個內部類(還原) ImageIdValueCallback :
private CompletableFuture<String> buildCompletableFuture(String imageId, String comId, int newGroup) {
Supplier<String> futureSupplier = () -> {
String lockKey = String.format("%s%s%s", comId, newGroup, imageId);
return redisLock.call(lockKey, new ImageIdValueCallback(imageId, comId, newGroup));
};
CompletableFuture<String> future = CompletableFuture.supplyAsync(futureSupplier, executorService);
return future;
}
class ImageIdValueCallback implements ValueLockCallback<String> {
private String imageId;
private String comId;
private int newGroup;
public ImageIdValueCallback(String imageId, String comId, int newGroup) {
this.imageId = imageId;
this.comId = comId;
this.newGroup = newGroup;
}
@Override
public String execute() {
return dealWith(comId, newGroup, imageId); // dealWith 是 redisLock.call 里面的 lambda 表達式里的代碼塊。
}
}
這樣,是不是清晰很多了 ?