1 有用部分
2 常用函数列表
demo1 方法和总结
demo2 方法
demo3优点: 函数式编程的优点是什么?为什么要使用函数式编程?
2 常用函数列表
接口 |参数 |返回类型 |描述
Predicate<T> T |boolean |用于判别一个对象。比如求一个人是否为男性
Consumer<T>, T void 用于接收一个对象进行处理但没有返回,比如接收一个人并打印他的名字
Function<T,R> T |R |转换一个对象为不同类型的对象
Supplier<T> |None T |提供一个对象
UnaryOperator<T> T T 接收对象并返回同类型的对象
BinaryOperator<T>|(T,T) T 接收两个同类型的对象,并返回一个原类型对象
3 demo1 关于Funtion<T,R>的应用(讲师没有给demo,自己写的,有不对的地方请指教)
需求:
把FWM狙击枪(其实是AWM)的属性赋给玩具枪
Gun接口:
package com.ddwei.chapter1.entity; public interface Gun { void shoot(); }
FWM实现类:
package com.ddwei.chapter1.entity; public class FWMGun implements Gun{ private String color; //枪体颜色 private String bulletNumber; //弹夹数 @Override public void shoot() { } /** * 有参构造函数 * @param color * @param bulletNumber */ public FWMGun(String color, String bulletNumber) { this.color = color; this.bulletNumber = bulletNumber; } @Override public String toString() { return "FWM狙击枪{" + "颜色为'" + color + '\'' + ", 子弹数量为'" + bulletNumber + '\'' + '}'; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getBulletNumber() { return bulletNumber; } public void setBulletNumber(String bulletNumber) { this.bulletNumber = bulletNumber; } }
ToyGun实现类:
package com.ddwei.chapter1.entity; /** * 玩具枪 */ public class ToyGun implements Gun{ private String color; //枪体颜色 private String bulletNumber; //弹夹数 @Override public void shoot() { } @Override public String toString() { return "玩具枪{" + "颜色为'" + color + '\'' + ", 子弹数量为'" + bulletNumber + '\'' + '}'; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public String getBulletNumber() { return bulletNumber; } public void setBulletNumber(String bulletNumber) { this.bulletNumber = bulletNumber; } }
服务类:
package com.ddwei.chapter1.entity; import java.util.function.Function; public class GunService implements Function {
/** 重写了apply方法
*/ @Override public ToyGun apply(Object o) { ToyGun toyGun = new ToyGun(); FWMGun fwmGun = (FWMGun) o; toyGun.setColor(fwmGun.getColor()); toyGun.setBulletNumber(fwmGun.getBulletNumber()); return toyGun; } }
测试类:
package com.ddwei.chapter1; import com.ddwei.chapter1.entity.FWMGun; import com.ddwei.chapter1.entity.Gun; import com.ddwei.chapter1.entity.GunService; import com.ddwei.chapter1.entity.ToyGun; import org.junit.Test; public class TestGun { @Test public void testChangeGun(){ //把fwm 狙击枪 的属性 赋给 玩具枪 //打印出玩具枪属性,方便和下方进行对比 Gun fwmGun = new FWMGun("金黄色","30"); ToyGun toyGun = new ToyGun(); toyGun.setColor("黑色"); toyGun.setBulletNumber("12"); System.out.println(fwmGun); System.out.println(toyGun); GunService gunService = new GunService(); toyGun = gunService.apply(fwmGun); System.out.println(toyGun); } }
打印日志:
FWM狙击枪{颜色为'金黄色', 子弹数量为'30'} 玩具枪{颜色为'黑色', 子弹数量为'12'} 玩具枪{颜色为'金黄色', 子弹数量为'30'} Process finished with exit code 0
自己理解:根据不同的业务场景(比如,A类向B类赋很多值,A类中C条记录 赋值 给D条记录),调用相应的接口,实现了规范化。
以后找类的时候,直接根据相应接口 的Ctrl T就可以找到。
4 demo2 关于Function的应用(网上摘抄改造的关于 函数式编程调用的应用)
接口:
package com.ddwei.chapter1.entity; public interface Clazz { public void m(); public void n(); }
实现类1:
package com.ddwei.chapter1.entity; public class Clazz1 implements Clazz{ public Clazz1() { System.out.println("Clazz1"); } @Override public void m(){ System.out.println("m1"); } @Override public void n() { System.out.println("n1"); } }
实现类2:
package com.ddwei.chapter1.entity; public class Clazz2 implements Clazz{ public Clazz2() { System.out.println("Clazz2"); } @Override public void m(){ System.out.println("m2"); } @Override public void n() { System.out.println("n2"); } }
测试类:
package com.ddwei.chapter1; import com.ddwei.chapter1.entity.Clazz; import com.ddwei.chapter1.entity.Clazz1; import com.ddwei.chapter1.entity.Clazz2; import java.util.function.Function; public class Main { public static void main(String[] args){ System.out.println("main"); Main main = new Main(); main.F(new Clazz1()); System.out.println("=========="); main.F(new Clazz2()); } public void F(Clazz clazz){ //声明函数f Function f = Function.identity(); //将函数应用到类中(可能是不同的类) clazz = (Clazz) f.apply(clazz); clazz.n(); } }
打印日志:
main Clazz1 n1 ========== Clazz2 n2 Process finished with exit code 0
问题:
4.1 优点:参照demo3
4.2 这个函数式编程不满足 接口中必须只有一个方法的定义啊,详细参考2-9中第5条
5 demo3 关于为什么要用函数式接口
需求:
如果我是顺丰,我来负责淘宝,京东和拼多多的商品配送服务。我需要设计一个根据订单信息计算邮费的接口,三个电商网站系统调用我这个接口给用户计算邮费。应该怎么设计?
需要考虑如下几个问题点:
第一:三个电商有自己不同的免邮费政策,比如:淘宝大于100件包邮,京东订单满99包邮,拼多多...如何才能在邮费计算的接口中根据不同电商平台,分别调用他们的免邮政策呢?
第二:顺丰有自己的邮费计算规则,比如:基础运费10元,超重增加10元,超体积增加10元...这部分逻辑应该是通用的,只要不免邮费,就要调用这段逻辑计算邮费。如何将个性化的逻辑和通用的逻辑整合到一个接口中呢?
第三:如何设计才能最容易扩展,为以后对接其他平台预留灵活性?
常规设计:
函数式编程设计:
优点:
函数式接口就是将业务逻辑参数化。
第一:邮费计算接口中只包含相对固定,通用的业务逻辑,将定制化强的业务逻辑作为一个参数,让调用方自己定义。
第二:以后扩展第四家也非常简单,因为接口是通用的。
第三:以后如果扩展接口的实现逻辑,比如:当判断免邮后,记录一条免邮信息。或者给用户发送免邮短信等。只需要稍作修改就行。
类似与规则引擎,只需要给我订单信息和规则,我会自动计算。例如 金额小于1000的规则, 规则中金额入参1000,订单中自带金额 ,让两个金额比较。