第五章、Groovy闭包

1、优雅介绍闭包

  • 一段代码块作为一个对象看待
  • it作为提供闭包的默认名称

2、闭包场景

2.1、使用迭代器(iterators)

// java 5
for (ItemType item : list){
  // 具体逻辑
}

// groovy 对象
list.each{ item -> 
  // 具体逻辑
}
  
// java 8 with lambda
list.stream().forEach((item) -> {
  // 具体逻辑
})  

// java 8 groovy 闭包
list.stream().forEach{println it}


2.2、 使用一个协议处理资源

  • new File('myfile.txt').eachLine{println it}
    
    // handler
    //java a @FuncionalInterface in java 8
    interface ResourceUser{
      void use(Resource resource)
    }
    // 使用
    resourceHandler.handle(new ResourceUser(){
      public void use (Resource resource){
        resource.doSomething()
      }
    });
    
    // groovy 
    resourceHandler.handle{ resource -> resource.doSomething()}
    

3、声明闭包

3.1、简单申明

  • /**
     * 简单闭包申明
     * @author liangchen* @date 2020/11/4
     */
    class SimpleDeclarationDemo {
    
        static void main(String[] args) {
    
            // 自定义参数名 counter
            def  log = ""
            (1..10).each { counter -> log += counter}
    
            assert  log == '12345678910'
    
            // it就是默认参数名称
            log = ''
            (1..10).each { log += it }
            assert  log == '12345678910'
    
        }
    }
    

3.2、为声明赋值

  • /**
     * 闭包定义
     * @author liangchen* @date 2020/11/4
     */
    class AssignmentClosure {
    
    
        static void main(String[] args) {
           AssignmentClosure assignmentClosure =  new AssignmentClosure()
            def t= 1111 
            assignmentClosure.printers.call(t)
        }
        // 闭包定义方式一
        def printers = { line -> println line}
    
        // 方式二
        Closure getPrinter(){
            return { line -> println line}
        }
    }
    

3.3、闭包对应多个方法

  • 闭包也可以用于查询 过滤条件

    • /**
       * @author liangchen* @date 2020/11/4
       */
      class MultiMethodSample {
      
          static void main(String[] args) {
              SizeFilter filter1 = new SizeFilter(limit: 6)
              SizeFilter filter2 = new SizeFilter(limit: 5)
      
              // 方法闭包赋值
              Closure sizeUpTo6 =  filter1.&sizeUpTo
              def words = ['long string', 'medium', 'short', 'tiny']
      
              assert 'medium' == words.find(sizeUpTo6)
              assert 'short' == words.find(filter2.&sizeUpTo)
      
              //=========
              // 根据不同参数找到不同闭包对应方法
              MultiMethodSample methodSample =  new MultiMethodSample()
              Closure multi = methodSample.&mysteryMethod
              assert  10 == multi('string arg')
              assert  3 == multi(['list','of','values'])
              assert 14 == multi(6, 8)
      
      
          }
      
          int mysteryMethod (String value){
              return value.length();
          }
      
          int mysteryMethod(List list) {
              return list.size();
          }
      
          int mysteryMethod(int x, int y) {
              return x + y
          }
      
      }
      
      /**
       * 大小过滤
       */
      class SizeFilter {
          Integer limit
      
          boolean sizeUpTo(String value) {
              return value.size() <= limit
          }
      }
      
      

3.4、 比较可选值

4、使用闭包

4.1、调用闭包

  • 有点类似

  • /**
     * 闭包定义规则,比如做一下,四则运算
     * @author liangchen* @date 2020/11/4
     */
    class CallingClosureDemo {
    
        static void main(String[] args) {
            def adder = { x, y -> return x + y }
    
            assert  adder(4,3) == 7
    
            assert adder.call(2, 6) == 8
            def slow = benchmark(10000) { (int) it / 2 }
            def fast = benchmark(10000) { it.intdiv(2) }
            assert  fast * 2 < slow
    
            def plus = calculate(1, 2) { x, y -> x + y }
            assert plus == 3
    
            def multi = calculate(1, 2) { x, y -> x * y }
            assert multi == 2
    
    
        }
    
        def static benchmark(int repeat, Closure worker){
            def start = System.nanoTime()
    
            repeat.times {worker(it)}
            def stop = System.nanoTime()
            return stop - start
        }
    
        def static calculate(int num1, int num2, Closure worker) {
           worker(num1, num2)
        }
    }
    
    

4.2、更多闭包能力

  • /**
     * 更多闭包特性 和 curry
     * @author liangchen* @date 2020/11/5
     */
    class MoreClosureDemo {
        static void main(String[] args) {
            //判断closure 参数是1
            assert numParams {one ->} == 1
            //判断closure 参数数量是2
            assert numParams { one, two -> } == 2
    
            // 判断参数类型
            assert paramTypes { String s -> } == [String]
            assert paramTypes {Number n, Date d ->} == [Number, Date]
    
            // currying 填充未知数
            def mult = { x, y, z -> return x * y * z }
            // {x,y,z -> return 2 * y * z}
            def twoTimes = mult.curry(2)
            // {x,y,z -> return 2 * 3 * z}
            def threeTimes = twoTimes.curry(3)
            // {x,y,z -> return 2 * 3 * 60}
            assert threeTimes(10) == 60
    
            // 将参数归纳一下, 有点类似定义抽象问题
            def configurator = {
                format, filter, line -> filter(line) ? format(line) : null
            }
            def appender = {config, append ,line  ->
                def out = config(line)
                if(out) append(out)
            }
            def dateFormatter = { line -> "${new Date()} : $line" }
    
            def debugFilter = { line -> line.contains('debug') }
            def consoleAppender = {line -> println line}
    
            def myConf = configurator.curry(dateFormatter, debugFilter)
            def myLog = appender.curry(myConf, consoleAppender)
            myLog("here is some debug message")
            myLog("this will not be printed")
    
    
            // 合并组合closure
            // currying 填充未知数
             mult = { x, y -> return x * y  }
            // {x,y,z -> return 2 * y * z}
            twoTimes = mult.curry(2)
            def fourTimes = twoTimes >> twoTimes
            def  eightTimes = twoTimes << fourTimes
    
            assert  eightTimes(1) == twoTimes(fourTimes(1))
    
            // 内存化 提高访问速度
            def fib
            fib = { it < 2 ? 1 : fib(it - 1) + fib(it - 2) }
            fib = fib.memoize()
            assert fib(40) == 165_580_141
    
            // trampoline 蹦床 防止递归栈溢出
            def last
            last = { it.size() == 1 ? it.head() : last.trampoline(it.tail()) }
            last = last.trampoline()
    
            assert  last(0..10_000) == 10_000
    
        }
    
    
        def static numParams(Closure closure) {
            closure.getMaximumNumberOfParameters()
        }
    
        def static paramTypes(Closure closure) {
            closure.getParameterTypes()
        }
    
    
    }
    
    

5、理解闭包域

  • 那个变量可以获得
  • 什么时候或怎么绑定到这值
  • 你怎么样控制这个作用域

5.1、简单变量域

  • /**
     * 闭包的作用域
     * @author liangchen* @date 2020/11/5
     */
    class ClosureScopeDemo {
    
        static void main(String[] args) {
            def x = 0
            10.times {
                x++
            }
            assert  x == 10
        }
    }
    
    

5.2、观察闭包域

  • /**
     * Closure域
     * @author liangchen* @date 2020/11/6
     */
    class InvestigateClosureScope {
        static void main(String[] args) {
    
            Mother julia = new Mother()
            def closure = julia.birth('param')
            // 获取closure上下文
            def context = closure.call()
    
            assert context[0] == julia
            assert context[1, 2] == ['prop', 'method']
            assert context[3, 4] == ['local', 'param']
            // 对象
            assert closure.thisObject == julia
            assert  closure.owner == julia
    
            // 代理
            assert closure.delegate == julia
            assert closure.resolveStrategy == Closure.OWNER_FIRST
    
            def map = [:]
            // map 进行代理
            map.with {
                a = 1
                b = 2
            }
            assert map == [a: 1, b: 2]
    
        }
    
    
    }
    
    class Mother {
        def prop = 'prop'
        def method(){
            'method'
        }
        Closure birth(param){
            def local = 'local'
            def closure = {
                [this, prop, method(), local, param]
            }
            return closure
        }
    }
    
    

5.3、经典累加测试

  • 累加器

  • /**
     *
     * groovy 累加器
     * @author liangchen* @date 2020/11/6
     */
    class AccumulatorTest {
    
        static void main(String[] args) {
            def accumulator = foo(1)
           // 1+2 ==3
            assert  accumulator(2) == 3
            // 3+1 ==4
            assert accumulator(1) == 4
            // 4+1==5
            assert accumulator(1) == 5
    
        }
    
       static def foo(n) {
            return { n += it }
    
        }
    
    }
    
    

6、闭门返回值

  • /**
     * closure 返回值
     * @author liangchen* @date 2020/11/6
     */
    class ClosureReturnDemo {
    
    
         static void main(String[] args) {
             // 不需要return
             def doubled =  [1,2,3].collect{it * 2}
             assert doubled == [2,4,6]
    
             // return 关键字
             doubled =  [1,2,3].collect { return it * 2 }
             assert doubled == [2,4,6]
    
             // 偶数 * 2, 奇数直接返回
             def odd= [1,2,3].collect {
                 if(it % 2 ==0) return it * 2
                return it
             }
             assert odd == [1,4,3]
         }
    }
    
    

7、支持设计模式

7.1、观察者模式

  • /**
     * 观察者模式
     * @author liangchen* @date 2020/11/6
     */
    class VisitorPatternDemo {
    
        static void main(String[] args) {
            def picture = new Drawing(shapes: [new Square(width: 1), new Circle(radius: 1)])
    
            def total = 0
            // 累加的Closure
            picture.accept {total += it.area()}
    
            println "The shapes in this drawing cover an area of $total units."
    
            println "The individual contributions are: "
    
            picture.accept {println it.class.name + ":" + it.area()}
        }
    }
    class Drawing {
        List shapes
    
        def accept(Closure yield){
            shapes.each {it.accept(yield)}
        }
    }
    
    class Shape {
        def accept(Closure yield){
            yield(this)
        }
    }
    
    class Square extends  Shape{
        def width
        def area() { width**2 }
    
    }
    class Circle extends Shape{
        def radius
    
        def area() { Math.PI * radius**2 }
    
    }
    
    
    

8、总结

  • 一段代码也是算是一个Closure
  • 有点类似java lambda风格
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值