Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java回退模式_Java_Design Patterns_Strategy Pattern_Fallback_Proxy Pattern - Fatal编程技术网

Java回退模式

Java回退模式,java,design-patterns,strategy-pattern,fallback,proxy-pattern,Java,Design Patterns,Strategy Pattern,Fallback,Proxy Pattern,我试图找到一种很好的方法来实现一个依赖于第三方库类的服务。我还有一个“默认”实现,可以在库不可用或无法提供答案时用作回退 public interface Service { public Object compute1(); public Object compute2(); } public class DefaultService implements Service { @Override public Object compute1() {

我试图找到一种很好的方法来实现一个依赖于第三方库类的服务。我还有一个“默认”实现,可以在库不可用或无法提供答案时用作回退

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和默认机制几乎相同。此外,如果在服务中添加了另一个方法,则实现看起来几乎相同


是否有一种设计模式可以应用于此处(,),以使代码看起来更好,并使进一步添加的内容更少复制粘贴?

Netflix是最好的库之一。我不确定你是否需要这么重的东西。它将为您提供线程池、超时、回退、监视、运行时配置更改、短路等


基本上,它是一个库,用于保护您的代码不受其依赖性故障的影响。

在这方面,代理可能会对您有所帮助。下面的示例未经测试,但应能让您了解可以实施哪些措施:

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)
        );
    }
}

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

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();
        }
    }
}
公共类ServiceImpl实现服务{
服务defaultService=新的defaultService();
第三方服务第三方服务=新的第三方服务();
@凌驾
公共对象计算机1(){
返回运行(第三方服务::customCompute1,defaultService::compute1);
}
@凌驾
公共对象计算机2(){
返回运行(第三方服务::customCompute2,defaultService::compute2);
}
专用静态T运行(供应商操作、供应商回退){
试一试{
T result=action.get();
返回结果!=null?结果:fallback.get();
}捕获(例外e){
返回fallback.get();
}
}
}

您使用的Java版本是什么?Hystrix看起来很棒!我现在正在评估。它提供了比OP所要求的多得多的东西,但这可能是一件好事……感谢您提到Hystrix。我不知道,但这比我需要的要多,我们有一个关于增加LIB的相当严格的政策。尽管我怀疑如果这些方法带有参数,这个解决方案是否能很好地应用。您必须为至少
函数
双函数
重载
运行
,然后您可能需要一个可伸缩性不好的。此外,
Service
的每一种新方法都需要在
serviceinpl
中进行相应的实现,这也不能很好地扩展,也可能是bug和维护问题的根源。同意@Didier的观点,虽然这是针对这种特定情况的解决方案,但不是一个很好的通用解决方案。方法句柄很酷,但可能不太适合这里。如果
fallback.get()
try
块中抛出异常,它将在
catch
块中重复。