Java 通过遵循Venkat Subramaniam';谁的书?

Java 通过遵循Venkat Subramaniam';谁的书?,java,generics,lambda,stream,method-reference,Java,Generics,Lambda,Stream,Method Reference,我是苏布拉曼尼亚姆教授的追随者。在这本书中,教授试图解释使用Lambda表达式委派的原则 我们使用lambda表达式和策略模式来分离 一种方法引起的关注。我们还可以使用它们将关注点与 一节课。从重用的角度来看,委托是一种更好的设计 工具比继承更重要。有了授权,就更容易改变方案 我们依赖的实现,我们可以插入不同的行为 更具活力。这有助于改变类的行为 独立于它们所依赖的部件的行为,并使 设计更灵活,无需强制深层的类层次结构 下面是一个具有静态方法的特定类,它执行所需的信息计算/获取 public

我是苏布拉曼尼亚姆教授的追随者。在这本书中,教授试图解释使用Lambda表达式委派的原则

我们使用lambda表达式和策略模式来分离 一种方法引起的关注。我们还可以使用它们将关注点与 一节课。从重用的角度来看,委托是一种更好的设计 工具比继承更重要。有了授权,就更容易改变方案 我们依赖的实现,我们可以插入不同的行为 更具活力。这有助于改变类的行为 独立于它们所依赖的部件的行为,并使 设计更灵活,无需强制深层的类层次结构

下面是一个具有静态方法的特定类,它执行所需的信息计算/获取

 public class YahooFinance {
        public static BigDecimal getPrice(final String ticker) {
            try {
                final URL url = new URL("http://ichart.finance.yahoo.com/table.csv?s=" + ticker);
                final BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
                final String data = reader.lines().skip(1).findFirst().get();
                final String[] dataItems = data.split(",");
                return new BigDecimal(dataItems[dataItems.length - 1]);
            } catch(Exception ex) {
                throw new RuntimeException(ex);
            }
        }
  }
创建代理
: 我们可以将其委托给lambda,而不是将部分责任委托给另一个类 表达式和方法引用。这将进一步减少阶级扩散

这是客户代码(即
代表
):

方法
send(requestPayload)
如下所示:

//Spring's abstraction for sending SOAP requests
public InsertInvoiceResponse send(InsertInvoiceRequest requestPayload) {
    return (InsertInvoiceResponse) getWebServiceTemplate()
    .marshalSendAndReceive("https://clienttesthorizon.horizonafs.com/AFSServices/AFSService.svc/basicHttpBinding", 
            requestPayload, new SoapActionCallback("http://tempuri.org/IAFSService/InsertInvoice")); 
}
   public class SoapCaller {
    
        private Executor<A, B, C> exec;
        
        public SoapCaller(final Executor<Class<T> t, Class<F> f, Class<E> e> execGeneric) {
            this.exec = execGeneric;
        }
        
        public InsertInvoiceResponse callWebService(Class<T> t,  Class<F> f) {
            
          return exec.apply(t, f);
        }
        
    }
public static void main(String[] args) {
    
    InvoiceTour it = db.getInvoiceTour();
    InvoiceLabTest ilt = db.getInvoiceLabTest();
    InvoicePenalty ip = db.getInvoicePenalty();
    
    Company c = db.getCompany();
    
    SoapCaller soapCallerForInvoiceTour = new SoapCaller(SoapHelper::getValueForTour);
    
    InsertInvoiceResponse invoiceTourResponse = soapCallerForInvoiceTour.callWebService(it, c);
    
    //do what ever with invoiceTourResponse
    
    SoapCaller soapCallerForInvoiceLabTest= new SoapCaller(SoapHelper::getValueForLabTest);
    
    InsertInvoiceResponse invoiceLabTestResponse = soapCallerForInvoiceTour.callWebService(ilt, c);
    
    //do what ever with invoiceLabTestResponse
    
}
我做了什么?

首先,我创建了功能接口,如下所示:

@FunctionalInterface
public interface Executor<A,B,C> { //A - stands for any InvoiceXXX; B - Company parameter and C will be result of soap response (InsertInvoiceResponse)
    
    C apply(A a, B b);
}
我的客户机代码应该是这样的:

//Spring's abstraction for sending SOAP requests
public InsertInvoiceResponse send(InsertInvoiceRequest requestPayload) {
    return (InsertInvoiceResponse) getWebServiceTemplate()
    .marshalSendAndReceive("https://clienttesthorizon.horizonafs.com/AFSServices/AFSService.svc/basicHttpBinding", 
            requestPayload, new SoapActionCallback("http://tempuri.org/IAFSService/InsertInvoice")); 
}
   public class SoapCaller {
    
        private Executor<A, B, C> exec;
        
        public SoapCaller(final Executor<Class<T> t, Class<F> f, Class<E> e> execGeneric) {
            this.exec = execGeneric;
        }
        
        public InsertInvoiceResponse callWebService(Class<T> t,  Class<F> f) {
            
          return exec.apply(t, f);
        }
        
    }
public static void main(String[] args) {
    
    InvoiceTour it = db.getInvoiceTour();
    InvoiceLabTest ilt = db.getInvoiceLabTest();
    InvoicePenalty ip = db.getInvoicePenalty();
    
    Company c = db.getCompany();
    
    SoapCaller soapCallerForInvoiceTour = new SoapCaller(SoapHelper::getValueForTour);
    
    InsertInvoiceResponse invoiceTourResponse = soapCallerForInvoiceTour.callWebService(it, c);
    
    //do what ever with invoiceTourResponse
    
    SoapCaller soapCallerForInvoiceLabTest= new SoapCaller(SoapHelper::getValueForLabTest);
    
    InsertInvoiceResponse invoiceLabTestResponse = soapCallerForInvoiceTour.callWebService(ilt, c);
    
    //do what ever with invoiceLabTestResponse
    
}

当然,也有编译错误的基调。我不确定如何实现功能接口,使其更通用(如果有意义的话)?有人知道如何使用lambda和方法引用使其更具可读性吗?

如果我很了解您,您希望
SoapCaller
(委托给lambda的类)也是泛型的,因此它可以定义如下:

class SoapCaller<T, U> {

    private BiFunction<T, U, InsertInvoiceResponse> soapExecutor;
    
    public SoapCaller(final BiFunction<T, U, InsertInvoiceResponse> soapExecutor) {
        this.soapExecutor= soapExecutor;
    }
    
    public InsertInvoiceResponse callWebService(T t, U u) {
      return soapExecutor.apply(t, u);
    }
    
}
SoapCaller<InvoiceTour, Company> soapCallerForInvoiceTour = new SoapCaller<>(SoapHelper::getValueForTour);
InsertInvoiceResponse invoiceTourResponse = soapCallerForInvoiceTour.callWebService(it, c);
    
//do what ever with invoiceTourResponse
    
SoapCaller<InvoiceLabTest, Company> soapCallerForInvoiceLabTest= new SoapCaller<>(SoapHelper::getValueForLabTest);
InsertInvoiceResponse invoiceLabTestResponse = soapCallerForInvoiceLabTest.callWebService(ilt, c);
您可以使用泛型参数,例如,如果您知道
公司
不会更改,则可以使删除类型参数:

class SoapCaller<T> {

    private BiFunction<T, Company, InsertInvoiceResponse> soapExecutor;

    ...
}
类SoapCaller{
专用双功能执行器;
...
}

Hi M A,是的,这看起来不错,目前我没有时间在我的示例中应用它,因为我的实际代码比这个showcase示例长得多。但我一测试你的答案就会投赞成票。同时,如果有人想添加不同的解决方案,请随意添加。