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

16-11-26 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));
    }
}
<p>

假如对某个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);
}
<p>

于是,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);    
}
<p>

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);    
}
<p>

它提供数据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);     
    }
<p>

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修改过]

              

3
猜你喜欢