Fra*_*kyi 3 java constructor default interface java-8
好吧,标题可能很难理解.我找不到正确的东西.所以,基本上我使用Java 8函数来创建可重试的API.我想要一个简单的接口实现,所以我在of(...)
Retryable接口的每个实现中创建了一个方法,我们可以使用lambda表达式,而不是手动创建一个匿名类.
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public interface Retryable<T, R> extends Function<T, R>{
void retrying(Exception e);
void skipping(Exception e);
int trials();
@Override
default R apply(T t) {
int trial = 0;
while (true) {
trial++;
try {
return action(t);
} catch (Exception e) {
if (trial < trials()) {
retrying(e);
} else {
skipping(e);
return null;
}
}
}
}
R action(T input) throws Exception;
interface RunnableRetryable extends Retryable<Void, Void> {
static RunnableRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedRunnable runnable) {
return new RunnableRetryable() {
@Override
public void retrying(Exception e) {
retrying.accept(e);
}
@Override
public void skipping(Exception e) {
skipping.accept(e);
}
@Override
public int trials() {
return trials;
}
@Override
public Void action(Void v) throws Exception {
runnable.tryRun();
return null;
}
};
}
@FunctionalInterface
interface CheckedRunnable extends Runnable {
void tryRun() throws Exception;
@Override
default void run() {
try {
tryRun();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface ConsumerRetryable<T> extends Retryable<T, Void> {
static <T> ConsumerRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedConsumer<T> consumer) {
return new ConsumerRetryable<T>() {
@Override
public void retrying(Exception e) {
retrying.accept(e);
}
@Override
public void skipping(Exception e) {
skipping.accept(e);
}
@Override
public int trials() {
return trials;
}
@Override
public Void action(T t) throws Exception {
consumer.tryAccept(t);
return null;
}
};
}
@FunctionalInterface
interface CheckedConsumer<T> extends Consumer<T> {
void tryAccept(T t) throws Exception;
@Override
default void accept(T t) {
try {
tryAccept(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface SupplierRetryable<T> extends Retryable<Void, T> {
static <T> SupplierRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedSupplier<T> supplier) {
return new SupplierRetryable<T>() {
@Override
public void retrying(Exception e) {
retrying.accept(e);
}
@Override
public void skipping(Exception e) {
skipping.accept(e);
}
@Override
public int trials() {
return trials;
}
@Override
public T action(Void v) throws Exception {
return supplier.tryGet();
}
};
}
@FunctionalInterface
interface CheckedSupplier<T> extends Supplier<T> {
T tryGet() throws Exception;
@Override
default T get() {
try {
return tryGet();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface FunctionRetryable<T, R> extends Retryable<T, R> {
static <T, R> FunctionRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedFunction<T, R> function) {
return new FunctionRetryable<T, R>() {
@Override
public void retrying(Exception e) {
retrying.accept(e);
}
@Override
public void skipping(Exception e) {
skipping.accept(e);
}
@Override
public int trials() {
return trials;
}
@Override
public R action(T t) throws Exception {
return function.tryApply(t);
}
};
}
@FunctionalInterface
interface CheckedFunction<T, R> extends Function<T, R> {
R tryApply(T t) throws Exception;
@Override
default R apply(T t) {
try {
return tryApply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但正如您所看到的,每种of(...)
方法都有很多重复的代码.我可以创造出一种"构造"的(这是不正确的单词,因为接口不能有构造函数)在可重试界面,但我不知道怎么办.有人有想法吗?
主要问题是你的API爆炸.扩展的所有这些嵌套接口Retryable
都不会添加任何功能,但是一旦它们成为API的一部分,就需要此代码的用户处理它们.此外,它们是此代码重复的原因,因为这些冗余接口中的每一个都需要其自己的实现,而所有实现基本上都是相同的.
删除这些过时类型后,您可以简单地将操作实现为委托:
public interface Retryable<T, R> extends Function<T, R>{
void retrying(Exception e);
void skipping(Exception e);
int trials();
@Override default R apply(T t) {
try { return action(t); }
catch(Exception e) {
for(int trial = 1; trial < trials(); trial++) {
retrying(e);
try { return action(t); } catch (Exception next) { e=next; }
}
skipping(e);
return null;
}
}
R action(T input) throws Exception;
public static Retryable<Void, Void> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedRunnable runnable) {
return of(retrying, skipping, trials, x -> { runnable.tryRun(); return null; });
}
@FunctionalInterface interface CheckedRunnable extends Runnable {
void tryRun() throws Exception;
@Override default void run() {
try { tryRun(); } catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T> Retryable<T, Void> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedConsumer<T> consumer) {
return of(retrying, skipping, trials,
value -> { consumer.tryAccept(value); return null; });
}
@FunctionalInterface interface CheckedConsumer<T> extends Consumer<T> {
void tryAccept(T t) throws Exception;
@Override default void accept(T t) {
try { tryAccept(t); } catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T> Retryable<Void, T> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedSupplier<T> supplier) {
return of(retrying, skipping, trials, voidArg -> { return supplier.tryGet(); });
}
@FunctionalInterface interface CheckedSupplier<T> extends Supplier<T> {
T tryGet() throws Exception;
@Override default T get() {
try { return tryGet(); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T, R> Retryable<T, R> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedFunction<T, R> function) {
return new Retryable<T, R>() {
@Override public void retrying(Exception e) { retrying.accept(e); }
@Override public void skipping(Exception e) { skipping.accept(e); }
@Override public int trials() { return trials; }
@Override public R action(T t) throws Exception {
return function.tryApply(t);
}
};
}
@FunctionalInterface interface CheckedFunction<T, R> extends Function<T, R> {
R tryApply(T t) throws Exception;
@Override default R apply(T t) {
try { return tryApply(t); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
}
Run Code Online (Sandbox Code Playgroud)
只需要一个实现类,它必须能够处理一个参数和一个返回值,其他的可以简单地使用适配器函数委托给它,执行任一操作,删除参数或返回null
,或两者兼而有之.
对于大多数用例,lambda表达式的形状适合选择正确的方法,例如
Retryable<Void,Void> r = Retryable.of(e -> {}, e -> {}, 3, () -> {});
Retryable<Void,String> s = Retryable.of(e -> {}, e -> {}, 3, () -> "foo");
Retryable<Integer,Integer> f = Retryable.of(e -> {}, e -> {}, 3, i -> i/0);
Run Code Online (Sandbox Code Playgroud)
但有时需要一点提示:
// braces required to disambiguate between Function and Consumer
Retryable<String,Void> c = Retryable.of(e->{}, e ->{}, 3,
str -> { System.out.println(str); });
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
123 次 |
最近记录: |