桥接模式和嵌套lambda表达式@yqj2065

桥接模式和嵌套lambda表达式
大家看看,欢迎拍砖。

上课时,我们在策略模式的基础上,介绍了其推广模板方法模式与桥接模式。 n次策略模式
2次行为参数化(可变部分)是独立的,则模板方法模式
2次行为参数化(可变部分)是串接的,则桥接模式。
1.桥接模式

例如对某个int x和y进行某种操作,如x*x + x*y,可以编写函数


package higherOrderFunction;
import static util.Print.*;
/**
*
* @author yqj2065
*/
public class ReturnFunction {
public static int twoStep(int x, int y) {
return x*x + x*y;
}
public static void main(String[] arg) {
//使用twoStep(int,int)
pln(twoStep(2,3));
}
}

假如对某个int x进行某种(由用户指定)操作,然后加上x*y,则可以编写函数
public static int twoStep(IntUnaryOperator op, int x, int y) {
return op.applyAsInt(x) + x*y;
}
这里,对行为x*x加以参数化。显然,我们可以对+ x*y加以参数化。注意,我们是在IntUnaryOperator op1的基础上进行第二步操作。
public static int twoStep(IntUnaryOperator op1, int x, IntBinaryOperator op2,int y) {
int i = op1.applyAsInt(x);
int result = op2.applyAsInt(i, y);//桥接模式
//int result = op1.applyAsInt(x)+op2.applyAsInt(x, y) ;//模板方法模式
return result;
}
在这个方法中,能够清楚地看到模板方法模式与桥接模式的不同。我们在main()中编写测试代码:
pln(twoStep(2,3)); //对于twoStep(int,int),简单而直观
int i = twoStep(x -> x * x, 2, 3); pln("1:"+i); //对于twoStep(IntUnaryOperator,int,int),2*2+2*3,也简单。结果10
桥接模式的twoStep(IntUnaryOperator op1, int x, IntBinaryOperator op2,int y),如何完成上一个测试,结果10呢?
int j = twoStep(x -> x * x, 2,(x,y)->x*x+x*y, 3); pln("2e1:"+j);
错误。IntBinaryOperator参数的用法为op2.applyAsInt( op1.applyAsInt(x), y)
正确的lambda表达式为(x,y)->x+2*y:
int j = twoStep(x -> x * x, 2,(temp,y)->temp+2*y, 3); pln("2:"+j);//
其中有一个非常让人不爽的2,作为x的实参的2,在lambda表达式中要写出来。再例如
i = twoStep(x -> x * 5, 4, 3); pln("3:"+i); //32
j = twoStep(x -> x * 5, 4,(x,y)->x+4*y, 3); pln("4:"+j);//32


2.函数作为返回值

我们可以将int twoStep(IntUnaryOperator op1, int x, IntBinaryOperator op2,int y)重构为函数接口


package util;
import java.util.function.IntUnaryOperator;
public interface TwoStep {
int secondOP(IntUnaryOperator firstOP, int x,int y);
}

于是,main中的测试代码
//使用TwoStep
TwoStep ts = (step1, x,y)->step1.applyAsInt(x)+x*y;
i=ts .secondOP(x -> x * x, 2, 3);pln("3:"+i);
TwoStep能够很好地完成任务,也避免了在lambda表达式中写常数的尴尬。
大多数情况下,我们习惯某种数据或实体对象作为返回值。


package util;
import java.util.function.IntUnaryOperator;
public interface MyTwoStep {
int secondOP(IntUnaryOperator firstOP, int x);
}

MyTwoStep比TwoStep少了参数int y,直接在main中测试时,需要额外提供数据
final int a=3;
MyTwoStep op2 = (firstOP,x) -> firstOP.applyAsInt(x) +x*a;
i = op2.secondOP(x -> x * x,2); pln("4:"+i);
这并不有趣。我们现在定义一个复合操作,


package util;
public interface CompositeOP {
MyTwoStep op(int y);
}

它提供数据y,并返回一个函数。在main中测试
CompositeOP op1 = (y) -> {return (firstOP,x) -> firstOP.applyAsInt(x) + x*y;};
i = op1.op(3).secondOP(x -> x * x,2); pln("5:"+i);
3.嵌套lambda表达式

CompositeOP op1 = (y) -> {return (firstOP,x) -> firstOP.applyAsInt(x) + x*y;};
的简化版本:
CompositeOP op1 = y->(firstOP,x) -> firstOP.applyAsInt(x) + x*y;
这种嵌套lambda表达式反映了桥接模式的本质——串接的行为参数化。

附:main


public static void main(String[] arg) {
//使用twoStep(int,int)
pln(twoStep(2,3));
int i = twoStep(x -> x * x, 2, 3); pln(
"1:"+i);
int j = twoStep(x -> x * x, 2,(x,y)->x+2*y, 3); pln(
"2:"+j);
j = twoStep(x -> x * x, 2,(x,y)->x*x+x*y, 3); pln(
"2e1:"+j);
i = twoStep(x -> x * 5, 4, 3); pln(
"1-1:"+i);
j = twoStep(x -> x * 5, 4,(x,y)->x+4*y, 3); pln(
"2-1:"+j);

//使用TwoStep
TwoStep ts = (step1, x,y)->step1.applyAsInt(x)+x*y;
i=ts .secondOP(x -> x * x, 2, 3);pln(
"3:"+i);
//直接使用MyTwoStep
final int a=3;
MyTwoStep op2 = (firstOP,x) -> firstOP.applyAsInt(x) +x*a;
i = op2.secondOP(x -> x * x,2); pln(
"4:"+i);
//使用CompositeOP
// CompositeOP op1 = (y) -> {return (firstOP,x) -> firstOP.applyAsInt(x) + x*y;};
CompositeOP op1 = y->(firstOP,x) -> firstOP.applyAsInt(x) + x*y;
i = op1.op(3).secondOP(x -> x * x,2);pln(
"5:"+i);
}

10
1:10
2:10
2e1:28
1-1:32
2-1:32
3:10
4:10
5:10

贴代码怎么不行呢??
[该贴被yqj2065于2016-11-26 17:32修改过]
[该贴被yqj2065于2016-11-26 17:33修改过]
[该贴被yqj2065于2016-11-26 17:39修改过]