13

我正在尝试找到一种实现依赖于第三方库类的服务的好方法。如果库不可用或无法提供答案,我还有一个“默认”实现用作后备。

public interface Service {

    public Object compute1();

    public Object compute2();
}

public class DefaultService implements Service {

    @Override
    public Object compute1() {
       // ...
    }

    @Override
    public Object compute2() {
        // ...
    }
}

服务的实际实现类似于:

public class ServiceImpl implements Service {
    Service defaultService = new DefaultService();
    ThirdPartyService thirdPartyService = new ThirdPartyService();

    @Override
    public Object compute1() {
        try {
            Object obj = thirdPartyService.customCompute1();
            return obj != null ? obj : defaultService.compute1();
        } 
        catch (Exception e) {
            return defaultService.compute1();
        }
    }

    @Override
    public Object compute2() {
        try {
            Object obj = thirdPartyService.customCompute2();
            return obj != null ? obj : defaultService.compute2();
        } 
        catch (Exception e) {
            return defaultService.compute2();
        }
    }
}

当前的实现似乎有点重复,只有对服务的实际调用不同,但 try/catch 和默认机制几乎相同。此外,如果在服务中添加了另一种方法,则实现看起来几乎相同。

是否有可能适用于此处的设计模式(代理策略)以使代码看起来更好并减少进一步的添加复制粘贴?

4

3 回答 3

3

您可以使用方法引用将公共逻辑提取到单独的方法中,例如:

public class ServiceImpl implements Service {
    Service defaultService = new DefaultService();
    ThirdPartyService thirdPartyService = new ThirdPartyService();

    @Override
    public Object compute1() {
        return run(thirdPartyService::customCompute1, defaultService::compute1);
    }

    @Override
    public Object compute2() {
        return run(thirdPartyService::customCompute2, defaultService::compute2);
    }

    private static <T> T run(Supplier<T> action, Supplier<T> fallback) {
        try {
            T result = action.get();
            return result != null ? result : fallback.get();
        } catch(Exception e) {
            return fallback.get();
        }
    }
}
于 2015-04-26T11:27:18.847 回答
3

最好的库之一是 Netflix 的Hystrix。我不确定您是否需要如此繁重的工作。它将为您提供线程池、超时、回退、监控、运行时配置更改、短路等。

基本上,它是一个库,可以保护您的代码免受其依赖项失败的影响。

于 2015-04-26T11:11:25.697 回答
3

代理可能会在这里为您提供帮助。下面的示例未经测试,但应该让您了解可以放置的内容:

public class FallbackService implements InvocationHandler {

    private final Service primaryService;
    private final Service fallbackService;

    private FallbackService(Service primaryService, Service fallbackService) {
        this.primaryService = primaryService;
        this.fallbackService = fallbackService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            Object result = method.invoke(primaryService, args);
            if (result != null) return result;
        } catch (Exception ignore) {}
        return method.invoke(fallbackService, args);
    }

    public static Service createFallbackService(Service primaryService, Service fallbackService) {
        return (Service) Proxy.newProxyInstance(
                Service.class.getClassLoader(),
                new Class[] { Service.class },
                new FallbackService(primaryService, fallbackService)
        );
    }
}
于 2015-04-26T11:24:39.783 回答