`
gordonAtJava
  • 浏览: 8042 次
文章分类
社区版块
存档分类
最新评论

在java中小试FP(二)

阅读更多
一些说明,仿佛没有说明的代码基本都没有人会看


以下代码是为了用200行以内的java代码实现一些functional programming的特性,并且可以直接用spring定义任意程序流程.

User类是一个pojo
UserHandler和UserValidator是包含一些业务逻辑的类,包含了一些业务方法,
包括一下方法
UserValidator.java
boolean validate(User u);


UserHandler.java
User demoActionOne(User u);
User demoActionTwo(User u);
String getRole(User u);
User makeTaller(User u);


现在可以直接通过对这些已经有的功能组合就能有新的功能,比如
这样的代码
User u = new User("gordon", 25, 173);
UserValidator v=new UserValidator();
UserHandler h=new UserHandler();
if(v.validate(u)){
  h.demoActionOne(u);
}else{
  h.demoActionTwo(u);
}


可以这样写
Functor validate=Functor.define(new UserValidator(),"validate");
Functor actOne=Functor.define(new UserHandler(),"demoActionOne");
Functor actTwo=Functor.define(new UserHandler(),"demoActionTwo");

Functor newProcess=validate.sw(true,actOne,false,actTwo);
User u = new User("gordon", 25, 173);
newProcess.apply(u);

这里的newProcess就是一个新的程序流程(或者说片断),
也可以使用标准的spring xml定义作为程序流程定制

比如
  <bean parent="define" id="validate">
      <constructor-arg ref="userValidator"/>
      <constructor-arg value="validate"/>
  </bean>
  <bean parent="define" id="actOne">  
    <constructor-arg ref="userHandler"/>  
    <constructor-arg value="demoActionOne"/>  
  </bean>  
  <bean parent="define" id="actTwo">  
    <constructor-arg ref="userHandler"/>  
    <constructor-arg value="demoActionTwo"/>  
  </bean>
  <bean id="process1" parent="choice">
    <constructor-arg ref="userRoleEq2driver"/>
    <constructor-arg><map>
          <entry><key><value type="boolean">true</value></key><ref bean="actOne"/></entry>
          <entry><key><value type="boolean">false</value></key><ref bean="actTwo"/></entry>
    </map></constructor-arg>
  </bean>





仔细考虑一下,用fp做个简单的流程拼装器应该会比较简单。
把上次的代码稍微修改一下,再配上spring就马上可以订制流程咯。

测试代码
Test.java
package com.gordon.functor.test;

import com.gordon.functor.Functor;

import com.gordon.functor.functors.EqualFunctor;
import com.gordon.functor.legacy.User;

import com.gordon.functor.legacy.UserHandler;
import com.gordon.functor.legacy.UserValidator;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) throws Exception {
        User u1 = new User("gordon", 25, 173);
        User u2 = new User("jiacheng",25,173);

        
        ApplicationContext context = new ClassPathXmlApplicationContext(
                 new String[] {"flow.xml"});
        Functor process3=(Functor)context.getBean("process1");
        process3.apply(u1);
        process3.apply(u2);
        
        System.out.println();
        
        Functor p2=(Functor)context.getBean("p2");
        p2.apply(u2);
        Functor p3=(Functor)context.getBean("setusername");
        p3.apply("testname",u2);
        System.out.println(u2);
        Functor setUserNameToLarry=p3.curry("larry");
        setUserNameToLarry.apply(u2);
        System.out.println(u2);
    }
}




流程定义文件
flow.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
  <!--common settings-->
  <bean id="sequence" abstract="true" class="com.gordon.functor.Combinator" factory-method="sequence"/>
  <bean id="choice" abstract="true" class="com.gordon.functor.Combinator" factory-method="sw"/>
  <bean id="define" abstract="true" class="com.gordon.functor.Combinator" factory-method="define"/>
  <bean id="eq" class="com.gordon.functor.functors.EqualFunctor"/>
  <bean id="eq2" abstract="true" factory-bean="eq" factory-method="to"/>
  
  <!--old system module/class/function-->
  <bean id="userValidator" class="com.gordon.functor.legacy.UserValidator"/>
  <bean id="userHandler" class="com.gordon.functor.legacy.UserHandler"/>
  
  <!--new function based on functor which shouldn't be created,for demo only-->
  <bean parent="define" id="demoActionOne">
    <constructor-arg ref="userHandler"/>
    <constructor-arg value="demoActionOne"/>
  </bean>
  <bean parent="define" id="demoActionTwo">
    <constructor-arg ref="userHandler"/>
    <constructor-arg value="demoActionTwo"/>
  </bean>
  
  <!--define step validation with old UserValidator class-->
  <bean parent="define" id="validate">
      <constructor-arg ref="userValidator"/>
      <constructor-arg value="validate"/>
  </bean>
  
  <!--define step makeTaller with old UserHandler class-->
  <bean parent="define" id="makeTaller">
      <constructor-arg ref="userHandler"/>
      <constructor-arg value="makeTaller"/>
  </bean>
  <!--define step getRole with old validator class-->
  <bean parent="define" id="getUserRole">
      <constructor-arg ref="userValidator"/>
      <constructor-arg value="getRole"/>
  </bean>

  <bean parent="define" id="setusername">
    <constructor-arg value="setName"/>
  </bean>
  
  <bean id="userRoleEq2driver" parent="sequence">
    <constructor-arg><list>
      <ref bean="getUserRole"/>
      <bean parent="eq2">
        <constructor-arg><value type="java.lang.String">driver</value></constructor-arg>
      </bean>
    </list></constructor-arg>
  </bean>
  
  <!--define process one-->
  <bean id="process1" parent="choice">
    <constructor-arg ref="userRoleEq2driver"/>
    <constructor-arg><map>
          <entry><key><value type="boolean">true</value></key><ref bean="demoActionOne"/></entry>
          <entry><key><value type="boolean">false</value></key><ref bean="demoActionTwo"/></entry>
    </map></constructor-arg>
  </bean>
  
  <bean id="p2" parent="sequence">
    <constructor-arg><list>
        <ref bean="process1"/>
        <ref bean="makeTaller"/>
        <ref bean="demoActionOne"/>
    </list></constructor-arg>
  </bean>
  
</beans>



核心类
Functor.java
package com.gordon.functor;

import java.util.HashMap;
import java.util.Map;

public abstract class Functor {
    public abstract Object apply(Object... args);

    public static Functor define(final String action){
        return new Functor() {
            public Object apply(Object... args){
                if(args==null)return null;
                if(args.length>1){
                    Object[] tail=new Object[args.length-1];
                    System.arraycopy(args,0,tail,0,tail.length);
                    return run(args[args.length-1],action,tail);
                }else{
                    return run(args[0],action);
                }
                
            }
        };
    }
    
    public static Functor define(final Object worker, final String action) {
        return new Functor() {
                public Object apply(Object... args) {
                    return run(worker, action, args);
                }
            };
    }

    public Functor and(final Functor... functors) {
        final Functor first = this;
        return new Functor() {
                public Object apply(Object... args) {
                    Boolean result = (Boolean)first.apply(args);
                    for (Functor f: functors) {
                        result = result && (Boolean)f.apply(args);
                    }
                    return result;
                }
            };
    }

    public Functor or(final Functor... functors) {
        final Functor first = this;
        return new Functor() {
                public Object apply(Object... args) {
                    Boolean result = (Boolean)first.apply(args);
                    for (Functor f: functors) {
                        result = result || (Boolean)f.apply(args);
                    }
                    return result;
                }
            };
    }

    public Functor sw(final Map<Object, Functor> switchMap) {
        final Functor f = this;
        return new Functor() {
                public Object apply(Object... args) {
                    Object firstResult = f.apply(args);
                    if (!switchMap.containsKey(firstResult))
                        return args;
                    return switchMap.get(firstResult).apply(args);
                }
            };
    }

    public Functor sw(Object... args) {
        if (args.length > 1 && args.length % 2 == 0) {
            Map<Object, Functor> sw = new HashMap<Object, Functor>();
            for (int i = 0; i < args.length; i = i + 2) {
                sw.put(args[i], (Functor)args[i + 1]);
            }
            return this.sw(sw);
        } else
            throw new java.lang.IllegalArgumentException("incorrect number of arguments for Functor.sw , correct format should be (case,Functor,case,Functor...)");
    }

    public Functor curry(final Object... pargs) {
        final Functor self = this;
        return new Functor() {
                public Object apply(Object... args) {
                    Object[] arg = new Object[pargs.length + args.length];
                    System.arraycopy(pargs, 0, arg, 0, pargs.length);
                    System.arraycopy(args, 0, arg, pargs.length, args.length);
                    return self.apply(arg);
                }
            };
    }

    public Functor then(final Functor... functors) {
        final Functor first = this;
        return new Functor() {
                public Object apply(Object... args) {
                    Object result = first.apply(args);
                    if (functors != null)
                        for (Functor f: functors) {
                            result = f.apply(result);
                        }
                    return result;
                }
            };
    }

    public Functor to(final Object... args) {
        return this.curry(args);
    }

    public Functor than(final Object... args) {
        return this.curry(args);
    }

    protected static Object run(Object worker, String action, 
                                Object... arguments) {
        java.lang.reflect.Method mx = null;
        for (java.lang.reflect.Method m: worker.getClass().getMethods()) {
            if (m.getName().equals(action)) {
                mx = m;
                break;
            }
        }
        Object result = null;
        try {
            if (!mx.isVarArgs()) {
                result = mx.invoke(worker, arguments);
            } else {
                if (arguments.length == mx.getParameterTypes().length) {
                    result = mx.invoke(worker, arguments);
                } else {
                    Object[] args = new Object[mx.getParameterTypes().length];
                    for (int i = 0; i < args.length; i++) {
                        if (i != args.length - 1)
                            args[i] = arguments[i];
                        else {
                            Object[] var = 
                                (Object[])java.lang.reflect.Array.newInstance(mx.getParameterTypes()[i].getComponentType(), 
                                                                              arguments.length - 
                                                                              i);
                            System.arraycopy(arguments, i, var, 0, var.length);
                            args[i] = var;
                        }
                    }
                    result = mx.invoke(worker, args);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}



这个类是为了给spring写配置简单写用的
Combinator.java
package com.gordon.functor;

import java.util.List;
import java.util.Map;

public abstract class Combinator {
    
    public static Functor and(Functor... functors){
        if(functors!=null) return head(functors).and(tail(functors));
        else return null;
    }
    
    public static Functor and(List<Functor> functors){
        if(functors!=null) return and(functors.toArray(new Functor[functors.size()]));
        else return null;
    }
    
    public static Functor or(Functor... functors){
        if(functors!=null) return head(functors).or(tail(functors));
        else return null;
    }
    
    public static Functor or(List<Functor> functors){
        if(functors!=null) return or(functors.toArray(new Functor[functors.size()]));
        else return null;
    }
    
    public static Functor sw(Functor choice,Map<Object,Functor> switchMap){
        return choice.sw(switchMap);
    }
    
    public static Functor sw(Functor choice,Object... args){
        return choice.sw(args);
    }
    
    public static Functor curry(Functor self,Object... args){
        return self.curry(args);
    }
    
    public static Functor sequence(List<Functor> functors){
        return sequence(functors.toArray(new Functor[functors.size()]));
    }
    
    public static Functor sequence(Functor[] functors){
        if(functors!=null) return head(functors).then(tail(functors));
        else return null;
    }
    
    private static Functor head(Functor[] array){
        if(array!=null&&array.length>0)return array[0];
        else return null;
    }
    
    private static Functor[] tail(Functor[] array){
        if(array.length<2) return null;
        Functor[] tail=new Functor[array.length-1];
        System.arraycopy(array,1,tail,0,array.length-1);
        return tail;
    }
    public static Functor define(Object worker,String action){
        return Functor.define(worker,action);
    }
    public static Functor define(String action){
        return Functor.define(action);
    }
}



一个基本的用来判断相等的Functor类
EqualFunctor.java
package com.gordon.functor.functors;

import com.gordon.functor.Functor;

public class EqualFunctor extends Functor {
    public EqualFunctor() {
    }

    public Object apply(Object... args) {
        if(args.length<2) return null;
        return args[0].equals(args[1]);
    }
}



测试用的其他类
User.java
package com.gordon.functor.legacy;

public class User{
	private String name;
	private int age;
	private int height;
	public User(String name,int age,int height){
		this.name=name;
		this.age=age;
		this.height=height;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public String toString(){
            return "{name:"+this.name+",age:"+this.age+",height:"+this.height+"}";
        }
}


UserHandler.java
package com.gordon.functor.legacy;

public class UserHandler {
    public UserHandler() {
    }
    public User makeTaller(User u){
        if(u!=null)u.setHeight(u.getHeight()+10);
        return u;
    }
    public User demoActionOne(User u){
        System.out.println("this is demo action one");
        if(u!=null){
            System.out.println("user="+u);
        }
        return u;
    }
    public User demoActionTwo(User u){
        System.out.println("this is demo action two");
        if(u!=null){
            System.out.println("user="+u);
        }
        return u;
    }
}


UserValidator.java
package com.gordon.functor.legacy;

public class UserValidator{
    public boolean validate(User u){
        return (u.getName().equals("gordon"));
    }
    public String getRole(User u){
        if(u.getName().equals("gordon"))return "developer";
        if(u.getName().equals("jiacheng"))return "driver";
        if(u.getName().equals("dylan"))return "dba";
        return "staff";
    }
}
分享到:
评论
2 楼 gordonAtJava 2008-03-01  
在java中实现functional programming的一些特性,并且可以和spring直接结合做流程引擎,具体请看刚补上的说明
ray_linn 写道
能不能先告诉我这一大段到底是要干什么?

1 楼 ray_linn 2008-02-29  
能不能先告诉我这一大段到底是要干什么?

相关推荐

    mongodb在java中小试牛刀

    MongoDB在Java中被广泛用于构建高性能、可扩展的数据存储解决方案。MongoDB是一个NoSQL数据库,以其灵活性、可伸缩性和高性能而闻名。在Java中使用MongoDB,我们可以借助Spring Data MongoDB框架,它提供了一种简化...

    Java Hessian小试(转)

    在Java中,使用Hessian主要涉及以下几个步骤: **1. 引入依赖** 在项目中引入Hessian的库,通常是Caucho公司的Hessian库,可以通过Maven或Gradle添加依赖。 **2. 定义服务接口** 创建一个Java接口,声明需要暴露的...

    java画图板小试

    在这个项目中,我们将学习如何使用Java的Swing库来创建一个基本的图形用户界面,让用户能够进行简单的绘图操作。 【描述】这篇博客文章通过一个具体的实例,向读者展示了如何在Java环境中构建一个简单的画图应用。...

    Java小试一个播放音乐器

    在Java中实现音乐播放功能,主要涉及到以下几个核心知识点: 1. **音频文件处理**:Java提供了一系列的类库来处理音频文件,如`javax.sound.sampled`包中的`AudioSystem`和`AudioInputStream`等。这些类允许开发者...

    Java HttpInvoker小试(转)

    NULL 博文链接:https://zhuchengzzcc.iteye.com/blog/1534671

    JAVA 计算均值

    java 计算均值 小试身手

    java-swing编程小试牛刀之图片查看器

    当用户在`RightPanel`中选择不同的图片时,`MainPanel`中的图片会相应更新。 - **右侧边栏** (`RightPanel`): 显示同一文件夹下的所有图片缩略图,用户可以通过点击这些缩略图来切换`MainPanel`中的图片。 - 当图片...

    第二周牛刀小试测试题答案1

    1. 营销漏斗理论:在描述中提到的“营销漏斗”,是指潜在客户从认知品牌到最终购买的过程,通常分为曝光与发现、考虑与购买意图、采取行动和复购等阶段。对于刚建立的户外用品电商网站,目标是增加品牌知名度,所以...

    Java实验指导书 2009

    - 分析Java中的关键字和保留字,了解它们的作用和用法。 **小试牛刀:** - 实践基本的数据类型操作,如整型、浮点型、字符型等。 - 编写简单的控制结构程序,如if-else语句、switch-case语句。 **挑战自我:** - ...

    用JAVA实现3个数排序

    用JAVA实现的排序额 学JAVA 小试身手

    JExcel / 小试牛刀

    在JExcelOperate.java中,通常会包括以下步骤: 1. **导入JExcel库**:首先,我们需要导入JExcel所需的库,这通常是通过在代码顶部添加import语句完成的。 ```java import net.sourceforge.jexcelapi.*; ``` 2. **...

    MVC新手小试牛刀-泡泡堂

    3. 控制器层:在Java中,控制器可能是Servlet或使用Spring MVC框架的Controller类。它们处理用户的HTTP请求,比如玩家的移动指令、释放炸弹的操作等,调用服务层方法进行处理,然后将响应数据(如更新的游戏状态)...

    通达信指标公式源码 小试牛刀精髓.doc

    本文档《通达信指标公式源码 小试牛刀精髓.doc》主要介绍了如何利用公式进行技术分析,帮助用户在股市中寻找潜在的投资机会。以下是其中涉及的一些关键知识点: 1. **移动平均线(MA)**: - 移动平均线是股票分析...

    java教学课件:第2章 Java小应用.ppt

    在Java编程中,小应用程序(Applet)是一种可以在Web浏览器中运行的轻量级程序。在本章"Java小应用"中,我们将深入探讨Applet的基本概念、生命周期及其在实践中的应用。 2.1 所有小应用程序的根源 Java的小应用程序...

    JNI技术小试

    在Java中,JNI提供了接口让Java代码能够调用本地(native)代码,通常是C或C++编写的库。这个过程涉及到以下几个主要步骤: 1. **定义本地方法**:在Java类中声明本地方法,方法的实现使用`native`关键字标注。例如...

    java版本websocket实例下载

    在Java中实现WebSocket,我们通常会用到JSR 356规范,这是Java EE 7引入的标准,提供了方便的API来创建WebSocket服务。 在本Java WebSocket实例中,我们将探讨以下几个关键知识点: 1. **WebSocket协议**:...

    小试牛刀代码(用于借鉴)

    在压缩包文件中,"jar"可能包含了一个包含JDBC驱动和其他相关库的Java档案,这些库使得Java程序能够与数据库进行通信。".idea"目录通常是IntelliJ IDEA这样的开发环境的项目配置文件,包含了一些元数据和设置。"JDBC...

    牛刀小试VC

    在《牛刀小试VC》中,读者将逐步了解如何利用VC++来创建、编译和调试C++程序。 首先,教程可能会介绍如何安装和配置VC++环境,包括设置开发环境、创建新项目以及管理工程文件。这部分内容对于初学者来说至关重要,...

    linux小试牛刀-项目开发

    在"第5季-小试牛刀-项目开发"的压缩包中,可能包含了关于以上各个知识点的实践教程、代码示例或者项目案例。通过学习这些内容,开发者可以深入理解Linux驱动开发的过程,掌握从识别硬件接口到编写驱动代码,再到测试...

Global site tag (gtag.js) - Google Analytics