为了账号安全,请及时绑定邮箱和手机立即绑定

【原创】从策略模式闲扯到lambda表达式

标签:
Java

引言

策略模式,讲这个模式的文章很多,但都缺乏一个循序渐进的过程。讲lambda表达式的文章也很多,但基本都是堆砌一堆的概念,很少带有自己的见解。博主一时兴起,想写一篇这二者的文章。需要说明的是,在看这篇文章的时候,请忘记所有的概念。容博主一步一步的带你们入坑。

正文

假设我们有一个Hero类,其UML图如下
image
这个时候,我们有一个需求:

  • 我们要找出type为刺客的Hero

这时,我们先封装一个要根据type类型来筛选Hero的方法

public static List<Hero> getHero(List<Hero> heroList, String type){
        List<Hero> result = new ArrayList<Hero>();        for(Hero hero : heroList){            if(type.equals(hero.getType())){
                result.add(hero);
            }
        }        return result;
    }

然后呢,做如下调用

getHero(heroList, "刺客");

突然有一天,产品突然改需求,现在的需求

  • 我们要找出stature(身高)大于170的Hero

也很简单嘛,再加一个重载的getHero方法就可以嘛,重载的getHero(ListheroList, int stature)方法如下

public static List<Hero> getHero(List<Hero> heroList, int stature){        List<Hero> result = new ArrayList<Hero>();        for(Hero hero : heroList){            if(hero.getStature() > stature){
                result.add(hero);
            }
        }        return result;
    }

然后呢,做如下调用

getHero(heroList, 170);

又过了几日,产品丧心病况的又改需求,现在最新的需求

  • 要找出stature(身高)大于170并且type类型为刺客的Hero

当然,你或许说了,可以再加一个getHero(ListheroList, String type, int stature)方法呀。不过呢,这种改法不够优雅。方法体中存在大量相同的代码,只是判断条件稍作改变。在这种情况下使用策略模式,就能够解决这个问题。
稍微介绍一下策略模式
策略模式
意图:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换,让算法独立于使用它的客户而独立变化。

主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

ps:在这里,上面的算法指的就是上面提到的判断条件。我们将判断条件封装为相应的类。

此时代码结构如下图所示
image
那么此时的getHero方法如下所示

public static List<Hero> getHero(List<Hero> heroList, Predicate<Hero> predicate){        List<Hero> result = new ArrayList<Hero>();        for(Hero hero : heroList){            if(predicate.test(hero)){
                result.add(hero);
            }
        }        return result;
    }

然后呢,根据需求做如下调用,想找那种类型的Hero,就传那种类型的Predicate进去。

getHero(heroList,new TMPredicate());

可是呢,机智的你又发现了一个缺陷,每次新增一个算法,要新加一个实现类。于是,机智的你提出,利用匿名内部类来做调用,不写实现类,于是调用代码变成下面这样

getHero(heroList,new Predicate<Hero>() {
    @Override
    public boolean test(Hero t) {
        return t.getStature() > 170 && "刺客".equals(t.getType());
    }
});

机智的你突然间又觉得:这么写,占用了太多的行数,看起来不够美观,于是,你决定用lambda表达式来改写,于是代码最终变成下面的样子

getHero(heroList,(t)->t.getStature() > 170 && "刺客".equals(t.getType()));

好了,到这里就结束了,是不是比我们最开始的版本简洁了不少,代码优雅了很多。lambda主要的目的就是提供一个更加简洁的代码结构,但是对于初学者,它可能反而增加阅读的难度。

当然,lambda表达式除了能简化代码代码意外,还能并行处理元素,充分利用多核CPU的性能,例如下面的代码

import java.util.Arrays;import java.util.List;public class Demo7 {    public static void main(String[] args) {        List<String> values = Arrays.asList("1","2","3","4");        print(values);
    }    public static void print(List<String> values){
       values.parallelStream().forEach(System.out :: println);//System.out表示对象,println表示方法
    }
}

输出如下

3
4
1
2

总结

本文以循序渐近的方式说明了,我们为什么要用策略模式以及如何用lambda表达式改写策略模式。希望大家有所收获。

参考文献

《JAVA8实战》

作者:孤独烟 出处: http://rjzheng.cnblogs.com/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文出处:https://www.cnblogs.com/rjzheng/p/9380465.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消