◎筱米加步枪◎.Blog

Happy coding

Commons Collections之函子(functor)综合学习

在公司没事做,无聊自己模拟情景来练习函子(functor)的使用。

自己定的一个场景:(自己假象出来的)
公司里面的工作的人有三种角色,分别是实习生、试用期员工、正式员工。
假定 :
实习生拿的基本工资是800元,试用期员工的基本工资是2000 ,正式员工的基本工资是3000。基本工资暂时是不会变的。实习生经过三个月的工作可以转成试用期员工,试用期员工经过三个月可以转到正式员工。每当一个项目完成后,正式员工可以拿到一部分分红,对于正式员工叫奖金,对于试用期员工叫补贴,实习生是没有的。

现在,有三个人,张三是实习生,李四是试用期员工,王五是正式员工。
要求模拟三个阶段:
1.刚开始,他们都在工作。
2.三个月后,张三变成了试用期员工,李四变成了正式员工。
3.项目结束后,试用期员工拿到补贴1500,正式员工拿到奖金5000
模拟三个阶段,张三、李四、王五拿到的总钱以及清单。


我用函子(functor),就是Apache Commons Collections提供的三个函子:
Predicate(逻辑判断器)、Transformer(对象转换器)、Closure(对象执行器)

实现如下:

首先看看人员角色的定义:

工作者抽象类:

/**
 * 劳动者,具体分成:实习生、试用期员工、正式员工
 * @create 2010-7-30
 */
public abstract class Worker {
	
	//姓名
	private String name;
		
	public Worker(String name){
		this.name = name;
	}

	/**
	 * 打印收入项目
	 * @return
	 */
	public abstract void printItem();
	
	/**
	 * 获取总共收入
	 * @return
	 */
	public abstract int getTotal();

	public String getName() {
		return name;
	}
}

实习生类:

/**
 * 实习生类
 * @create 2010-7-30
 */
public class Intern extends Worker{
	
	// 实习生基本工资800
	private final int salary = 800;
	
	public Intern(String name){
		super(name);
	}

	// 取得所有收入
	@Override
	public int getTotal() {
		return salary;
	}

	// 打印收入清单
	@Override
	public void printItem() {
		System.out.println(getName() + "[实习生]当月收入总收入为 [薪水" + salary + "元]=["
				+ getTotal() + "]元");
	}
}

试用期员工类:

/**
 * 试用期员工类
 * @create 2010-7-30
 */
public class Probationer extends Worker{

	//薪水=2000
	private final int salary = 2000;
	
	//试用期员工有补贴
	private int  allowance;
	
	public Probationer(String name){
		super(name);
	}

	public void setAllowance(int allowance) {
		this.allowance = allowance;
	}

	@Override
	public int getTotal() {
		return salary+allowance;
	}

	@Override
	public void printItem() {
		System.out.println(getName() + "[试用期员工]当月收入总收入为 [薪水" + salary
				+ "元]+[补贴" + allowance + "]=[" + getTotal() + "]元");
	}
}

正式员工类:

/**
 * 正式员工
 * @create 2010-7-30
 */
public class Employee extends Worker{
	
	//薪水 = 3000
	private final int salary = 3000;
	
	//正式员工有奖金
	private int bonus;
	
	public Employee(String name){
		super(name);
	}

	public void setBonus(int bonus) {
		this.bonus = bonus;
	}

	@Override
	public int getTotal() {
		return salary+bonus;
	}

	@Override
	public void printItem() {
		System.out.println(getName() + "[正式员工]当月收入总收入为 [薪水" + salary + "元]+[奖金"
				+ bonus + "]=[" + getTotal() + "]元");
	}
}

接下来,看看定义的两个转换器

实习生转试用期员工的转换器:

/**
 * 实习生转成 试用期员工 的一个 函子(functor)
 * @create 2010-7-30
 */
public class TransProbationer implements Transformer {

	@Override
	public Object transform(Object input) {
		Intern inter = (Intern) input;
		Probationer probationer = new Probationer(inter.getName());
		return probationer;
	}

}

试用期员工转成正式员工的转换器

/**
 * 试用期员工转成正式员工 的一个 函子(functor)
 * @create 2010-7-30
 */
public class TransEmployee implements Transformer {

	@Override
	public Object transform(Object input) {
		Probationer probationer = (Probationer) input;
		Employee employee = new Employee(probationer.getName());
		return employee;
	}
}

再来看看定义的两个执行器:

给试用期员工发1500补贴的执行器:

/**
 * 试用期员工发1500补贴 的 一个 函子
 * @create 2010-7-30
 */
public class AddAllowanceClosure implements Closure {

	@Override
	public void execute(Object input) {
		Probationer probationer = (Probationer) input;
		probationer.setAllowance(1500);
	}
}

给正式员工发5000奖金的执行器

/**
 * 正式员工发5000奖金的 一个 函子
 * @create 2010-7-30
 */
public class AddGonusClosure implements Closure {

	@Override
	public void execute(Object input) {
		Employee employee = (Employee) input;
		employee.setBonus(5000);
	}
}

开始模拟场景:

public class TestFunctor {
	
	public static void main(String[] args) {
		
		//定义是否是试用期员工的一个函子
		Predicate isProbationerPredicate = new InstanceofPredicate(
				Probationer.class);
		
		//定义是否是正式员工的一个函子
		Predicate isEmployeePredicate = new InstanceofPredicate(Employee.class);
		
		//定义三个劳动者 张三[实习生]、李四[试用期员工]、王五[正式员工]
		Worker zhansan = new Intern("张三");
		Worker lisi = new Probationer("李四");
		Worker wangwu = new Employee("王五");
		
		//查看目前收入
		System.out.println("\n来看看 张三、李四、王五目前的月收入:");
		zhansan.printItem();
		lisi.printItem();
		wangwu.printItem();
		
		//经过努力~~张三转成试用期员工了,李四转成正式员工了~
		System.out.println("\n\n3个月过去了,张三转成试用期员工了,李四转成正式员工了......");
		Transformer transProbationer = new TransProbationer();
		Transformer transEmployee = new TransEmployee();
		zhansan = (Worker) transProbationer.transform(zhansan);
		lisi = (Worker) transEmployee.transform(lisi);
		
		//查看目前收入
		System.out.println("\n来看看 张三、李四、王五目前的月收入:");
		zhansan.printItem();
		lisi.printItem();
		wangwu.printItem();
		
		
		//公司项目取得良好的成就,因此规定凡是试用期员工发补贴1500元,正式员工发奖金5000元
		System.out.println("\n\n目前公司取得很好的成绩,因此凡是试用期员工发补贴1500元,正式员工发奖金5000元");
		Map<Predicate , Closure> map = new HashMap<Predicate, Closure>();
		Closure allowanceClosure = new AddAllowanceClosure();
		Closure gonusClose = new AddGonusClosure();
		
		//如果是试用期员工,则发补贴
		map.put(isProbationerPredicate, allowanceClosure);
		//如果是正式员工,则发奖金
		map.put(isEmployeePredicate, gonusClose);
		//SwitchClosure是实现了Switch的闭包
		Closure rewards = SwitchClosure.getInstance(map);
		rewards.execute(zhansan);
		rewards.execute(lisi);
		rewards.execute(wangwu);
		
		System.out.println("\n来看看 张三、李四、王五目前的月收入:");
		zhansan.printItem();
		lisi.printItem();
		wangwu.printItem();
	}
}

运行结果:

来看看 张三、李四、王五目前的月收入:
张三[实习生]当月收入总收入为 [薪水800元]=[800]元
李四[试用期员工]当月收入总收入为 [薪水2000元]+[补贴0]=[2000]元
王五[正式员工]当月收入总收入为 [薪水3000元]+[奖金0]=[3000]元


3个月过去了,张三转成试用期员工了,李四转成正式员工了......

来看看 张三、李四、王五目前的月收入:
张三[试用期员工]当月收入总收入为 [薪水2000元]+[补贴0]=[2000]元
李四[正式员工]当月收入总收入为 [薪水3000元]+[奖金0]=[3000]元
王五[正式员工]当月收入总收入为 [薪水3000元]+[奖金0]=[3000]元


目前公司取得很好的成绩,因此凡是试用期员工发补贴1500元,正式员工发奖金5000元

来看看 张三、李四、王五目前的月收入:
张三[试用期员工]当月收入总收入为 [薪水2000元]+[补贴1500]=[3500]元
李四[正式员工]当月收入总收入为 [薪水3000元]+[奖金5000]=[8000]元
王五[正式员工]当月收入总收入为 [薪水3000元]+[奖金5000]=[8000]元

可以发现,使用函子可以把逻辑判断、对象转换、对象操作分离的很开,可以任意的自由的组合,通过组合达到所要的目的,代码上可能是多了点,但是对于抗击需求的变化是很好的,可以很好的扩展,可以任意的扩展对象操作,逻辑判断等。继续研究ing~~

Commons Collections之Predicates学习

今天无聊没事做,看到Commons Collections的东西,对Predicates接口和它下面挂着的几个类做了些研究,其实看了源代码之后,就知道很简单了。总结刚才的学习结果:

补充一下一个概念,函子(functor):执行操作或功能的部件,Predicates下面挂着的实现类就是一个函子,执行了各种逻辑运算和判断,你也可以根据自己的需要,实现Predicates类,实现evaluate方法,根据自己定义的算法来实现某一特定判断。

先看,Predicates的几个实现类,清单如下:

EqualPredicate
IdentityPredicate
NotPredicate
InstanceofPredicate
NullIsTruePredicate
NullIsFalsePredicate
NotNullPredicate
TruePredicate
FalsePredicate
UniquePredicate
AndPredicate
OrPredicate
AllPredicate
AnyPredicate
OnePredicate

并写了一个Demo程序,将几个Predicates的区别写在了程序的注释中,这是我的习惯。呵呵~~

public void testPredicate(){
		
		//相当于调用equals对比
		Predicate equal = new EqualPredicate("cst");  
		boolean resultEqual = equal.evaluate("cst");
		System.out.println("EqualPredicate:"+resultEqual);
		
		//相当于调用 == 对比
		Predicate identity = new IdentityPredicate(new String("cst"));
		boolean resultIdentity = identity.evaluate(new String("cst"));
		System.out.println("IdentityPredicate:"+resultIdentity);
		
		//装饰给定的Predicate指定对象想比,并返回相反的值
		Predicate not = new NotPredicate(equal);
		boolean resultNot = not.evaluate("cst");
		System.out.println("NotPredicate:"+resultNot);
		
		//相当于instanceof 对比
		Predicate instanceOf = new InstanceofPredicate(String.class);
		boolean resultInstanceof = instanceOf.evaluate("cst");
		System.out.println("InstanceofPredicate:"+resultInstanceof);
		
		// 装饰给定的Predicate
		//如果对象为null则返回true,否则返回给定Predicate的判定值
		Predicate  nullIsTrue = new NullIsTruePredicate(equal);
		boolean resultNullIsTrue = nullIsTrue.evaluate(null);
		System.out.println("NullIsTruePredicate:"+resultNullIsTrue);
		
		// 装饰给定的Predicate
		// 如果对象为null则返回false,否则返回给定Predicate的判定值
		Predicate  nullIsFalse = new NullIsFalsePredicate(equal);
		boolean resultNullIsFalse = nullIsFalse.evaluate(null);
		System.out.println("NullIsFalsePredicate:"+resultNullIsFalse);
		
		//当对象不为null时返回true
		Predicate notNull = NotNullPredicate.getInstance(); 
		boolean resultNotNull = notNull.evaluate(null);
		System.out.println("NotNullPredicate:"+resultNotNull);
		
		// 总是返回true
		Predicate truep = TruePredicate.getInstance(); 
		boolean resultTrue = truep.evaluate("cst");
		System.out.println("TruePredicate:"+resultTrue);
		
		// 总是返回false
		Predicate  falsep = FalsePredicate.getInstance();
		boolean resultFalse = falsep.evaluate("cst");
		System.out.println("FalsePredicate:"+resultFalse);
		
		// 首次evaluate判定对象总是返回true。
		// 其内部维护一个HashSet,每次调用evaluate(obj)
		//将会调用HashSet的add方法。该类常用于Collections过滤重复的对象。
		UniquePredicate unique = new UniquePredicate();
		boolean resultUnique1 = unique.evaluate("cst");
		boolean resultUnique2 = unique.evaluate("cst");
		System.out.println("UniquePredicate1:"+resultUnique1);
		System.out.println("UniquePredicate2:"+resultUnique2);
		
		
		///////////////////以下是实现复杂的逻辑/////////////////////////
		
		//装饰两个Predicate 判断返回两个Predicate和指定对象比较后and的结果
		Predicate and = new AndPredicate(equal, identity);
		boolean resultAnd = and.evaluate("cst");
		System.out.println("AndPredicate:"+resultAnd);
		
		//装饰两个Predicate 判断返回两个Predicate和指定对象比较后or的结果
		Predicate or = new OrPredicate(equal, identity);
		boolean resultOr = or.evaluate("cst");
		System.out.println("OrPredicate:"+resultOr);
		
		//多个Predicate指定对象比较后多个and的结果
		Predicate  [] predicates = new Predicate[]{equal,identity,not};
		Predicate all = new AllPredicate(predicates);
		boolean resultAll = all.evaluate("cst");
		System.out.println("AllPredicate:"+resultAll);
		
		//多个Predicate指定对象比较后多个or的结果
		Predicate any = new AnyPredicate(predicates);
		boolean resultAny = any.evaluate("cst");
		System.out.println("AnyPredicate:"+resultAny);
		
		//多个Predicate指定对象比较后,只要有一个结果为true就为true
		Predicate one = new OnePredicate(predicates);
		boolean resultOne = one.evaluate("cst");
		System.out.println("OnePredicate:"+resultOne);
	}

运行结果:

EqualPredicate:true
IdentityPredicate:false
NotPredicate:false
InstanceofPredicate:true
NullIsTruePredicate:true
NullIsFalsePredicate:false
NotNullPredicate:false
TruePredicate:true
FalsePredicate:false
UniquePredicate1:true
UniquePredicate2:false
AndPredicate:false
OrPredicate:true
AllPredicate:false
AnyPredicate:true
OnePredicate:tru

继续学习Commons Collections的其他东东~~了解下,方便日后少写人家已经实现过的代码。