2008-02-29
在java中小试FP(二)
关键字: fp
一些说明,仿佛没有说明的代码基本都没有人会看
以下代码是为了用200行以内的java代码实现一些functional programming的特性,并且可以直接用spring定义任意程序流程.
User类是一个pojo
UserHandler和UserValidator是包含一些业务逻辑的类,包含了一些业务方法,
包括一下方法
UserValidator.java
UserHandler.java
现在可以直接通过对这些已经有的功能组合就能有新的功能,比如
这样的代码
可以这样写
这里的newProcess就是一个新的程序流程(或者说片断),
也可以使用标准的spring xml定义作为程序流程定制
比如
仔细考虑一下,用fp做个简单的流程拼装器应该会比较简单。
把上次的代码稍微修改一下,再配上spring就马上可以订制流程咯。
测试代码
Test.java
流程定义文件
flow.xml
核心类
Functor.java
这个类是为了给spring写配置简单写用的
Combinator.java
一个基本的用来判断相等的Functor类
EqualFunctor.java
测试用的其他类
User.java
UserHandler.java
UserValidator.java
以下代码是为了用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";
}
}
评论
gordon@java
2008-03-01
在java中实现functional programming的一些特性,并且可以和spring直接结合做流程引擎,具体请看刚补上的说明
ray_linn 写道
能不能先告诉我这一大段到底是要干什么?
ray_linn
2008-02-29
能不能先告诉我这一大段到底是要干什么?
发表评论
提醒: 该博客已发表在公共论坛,博客所有留言会成为论坛回贴,留言请注意遵守论坛发贴规则
- 浏览: 725 次

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
在java中小试FP(一)
补充以下,http://www.javaeye.com/topic/7569 我 ...
-- by gordon@java -
在java中小试FP(二)
在java中实现functional programming的一些特性,并且可以 ...
-- by gordon@java -
在java中小试FP(二)
能不能先告诉我这一大段到底是要干什么?
-- by ray_linn -
javascript中的curry
gordon@java 写道笨笨狗 写道Prototype1.6就有这个扩展…… ...
-- by gordon@java -
javascript中的curry
笨笨狗 写道Prototype1.6就有这个扩展…… 嘿嘿,也是看了你的答复才 ...
-- by gordon@java






评论排行榜