繁体   English   中英

您如何重写在 Java 8 中使用泛型和函数并仅使用面向对象的混合 oop 和函数式编程的代码?

[英]How do you rewrite the code which using generics and functionals in Java 8 and mixing oop and functional programming by using only object-oriented?

我遇到过这种设计,但我没有完全掌握在 Java 8 中混合面向对象编程和函数式编程。

我对混合两种语言范式很感兴趣,而且互联网上的大多数教程都很简单,所以我无法通过混合来找到有关大规模软件设计的示例。 所以有了这个示例案例,我想我有机会挖掘它的某些案例。

在这种情况下,让我展示代码的相关部分。 这段代码包含一个通用的 FetchUtils 类,它实现了一个自定义迭代器,但为了简洁起见,我删除了一些部分。

public class FetchUtils<R, MSGIN, MSGOUT> {
    public SomeClass<R> getSomething(MSGIN query,
                                Function<MSGIN, MSGOUT> queryFunc,
                                Function<MSGOUT, List<R>> getResultList) {

               //...
                        MSGOUT callResult = queryFunc.apply(query);
                        buffer = getResultList.apply(callResult);
               //...
               //return someThing;
            }
            //...    
}

在客户端有一个函数定义和一个 lambda 表达式指向一个类的getCustomer方法的引用。 从客户端到使用泛型类型的上述方法的实际调用正在发送这些功能。

public class CustomerResponse {
   //...
   public List<Customer> getCustomer() {
        if (thing == null) {
            thing = new ArrayList<Customer>();
        }
        return this.customers;
    }
   //...
}

public class MyClient {

   //...

   @Autowired
   private FetchUtils<Customer, CustomerRequest, CustomerResponse> fetchUtils;

   //...

   public SomeClass<Customer> fetch() {

      //...

      Function<CustomerRequest, CustomerResponse> requestFunc = q -> {
            try {
                return myService.doSomething(q);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };

      CustomerRequest query = new CustomerRequest(/*...*/);

      return fetchUtils.getSomething(query,
                                     requestFunc,
                                     r -> r.getCustomer());

      //...
   }
   //...
}

您如何仅使用面向对象的编程即不传递高阶函数并且仅使用动态分派甚至不使用泛型来重写此代码?

如果没有泛型,这种设计是否可行?

类型推断如何与这些泛型类型和函数一起工作?

这个设计是否是混合函数式和面向对象编程的一个可能的例子,或者你如何评估这个设计?

您如何仅使用面向对象的编程即不传递高阶函数并且仅使用动态分派甚至不使用泛型来重写此代码?

class FuncImpl implements Function<CustomerRequest, CustomerResponse> {
    public CustomerResponse apply(CustomerResquest q) {
        try {
            return myService.doSomething(q);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
Function<CustomerRequest, CustomerResponse> requestFunc = new FuncImpl();

class FuncImpl2 implements Function<CustomerResponse,List<Customer>> {
    public List<Customer> apply(CustomerResponse r) {
        return r.getCustomer();
    }
}

...
return fetchUtils.getSomething(query, requestFunc,new FuncImpl2());

如果没有泛型,这种设计是否可行?

当然,在任何地方都强制执行具体类型。 (请参阅下面的类型推断并手工制作......)。

类型推断如何与这些泛型类型和函数一起工作?

泛型参数只是类型变量,所以你的例子很容易理解。

requestFun类型为Function<CustomerRequest, CustomerResponse>然后编译器可以很容易地推断出MSGINCustomerRequestMSGOUT CustomerResponse

对于r -> r.getCustomer()编译器已经知道MSGOUTCustomerResponse然后它查看CustomerResponse类型并发现getCustomer返回一个List<Customer>因此 lambda 的类型是Function<CustomerResponse,List<Customer>>然后RList<Customer>

这个设计是否是混合函数式和面向对象编程的一个可能的例子,或者你如何评估这个设计?

是的,这是一个很好的例子。

如果我对您的问题的理解是正确的,那么高阶函数是指您在代码中传递给getSomething方法的Function

一种思考方法可能是简单地表示类abstract每个类分配其定义的角色。 在一个示例中,以下代码执行与您共享的代码中相同的评估,但将不同的角色分配给各个单独的类。

abstract class Transform<I, O> {
    abstract O queryFunction(I input);
}

abstract class Group<O, R> {
    abstract List<R> groupIntoResult(O output);
}

abstract class FetchUtil<R, I, O> {
    Group<O, R> group;
    Transform<I, O> transform;

    public SomeClass<R> getSomething(I input) {
        O output = transform.queryFunction(input);
        List<R> grouped = group.groupIntoResult(transform.queryFunction(input));
        return new SomeClass<>(grouped);
    }
}

毫无疑问,您也可以根据这些 API 的使用情况将它们转换为interface 这就是您拥有的初始代码更接近实际使用名为Function FunctionalInterface类的地方。


为了进一步回答,这些不具有通用性的表示可以很容易地扩展为以下方式提供客户特定的实现

class Transformer extends Transform<CustomerRequest, CustomerResponse> {

    @AutoWired
    MySerice myService;

    @Override
    CustomerResponse queryFunction(CustomerRequest input) {
        try {
            return myService.doSomething(input);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

class Grouping extends Group<CustomerResponse, Customer> {
    @Override
    List<Customer> groupIntoResult(CustomerResponse output) {
        return output.getCustomer();
    }
}

请注意现在使用FetchUtil定义为您的客户端简化了任务。 它只需要提供请求对象,并且您将转换和分组实现绑定到您编写的实用程序类,以通过响应进行周转。

您的客户端代码最终缩短为以下几行,您会注意到这给使用您服务的客户端带来了怎样的负担:

public class MyClient {
    @AutoWired
    private FetchUtil<Customer, CustomerRequest, CustomerResponse> fetchUtil;
    // bind the above to appropriate Group and Transform implementation

    public SomeClass<Customer> fetch() {
        CustomerRequest query = new CustomerRequest(/*...*/);
        return fetchUtil.getSomething(query);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM