随着Java中lambda的出现,我们现在有了一个新工具,可以更好地设计我们的代码。 当然,第一步是使用流,方法引用和Java 8中引入的其他简洁功能。

展望未来,我认为下一步是重新访问完善的设计模式,并通过功能性编程视角进行了解。 为此,我将采用Decorator模式,并使用lambdas实现它。

我们将以装饰器模式的简单且美味的示例为例:在披萨中添加浇头。 这是GoF建议的标准实现:

首先,我们具有定义组件的接口:

public interface Pizza {String bakePizza();
}

我们有一个具体的组成部分:

public class BasicPizza implements Pizza {@Overridepublic String bakePizza() {return "Basic Pizza";}
}

我们决定必须以不同的方式装饰组件。 我们选择装饰器模式。 这是抽象装饰器:

public abstract class PizzaDecorator implements Pizza {private final Pizza pizza;protected PizzaDecorator(Pizza pizza) {this.pizza = pizza;}@Overridepublic String bakePizza() {return pizza.bakePizza();}
}

我们为组件提供了一些具体的装饰器:

public class ChickenTikkaPizza extends PizzaDecorator {protected ChickenTikkaPizza(Pizza pizza) {super(pizza);}@Overridepublic String bakePizza() {return super.bakePizza() + " with chicken topping";}
}public class ProsciuttoPizza extends PizzaDecorator {protected ProsciuttoPizza(Pizza pizza) {super(pizza);}@Overridepublic String bakePizza() {return super.bakePizza() + " with prosciutto";}
}

这是使用新结构的方式:

Pizza pizza = new ChickenTikkaPizza(new BasicPizza());
String finishedPizza = pizza.bakePizza();   //Basic Pizza with chicken toppingpizza = new ChickenTikkaPizza(new ProsciuttoPizza(new BasicPizza()));
finishedPizza  = pizza.bakePizza();  //Basic Pizza with prosciutto with chicken topping

我们可以看到这会变得非常混乱,如果考虑如何处理Java中的缓冲读取器,它的确会变得非常混乱:

new DataInputStream(new BufferedInputStream(new FileInputStream(new File("myfile.txt"))))

当然,您可以将其拆分为多行,但这不会解决混乱问题,只会分散它。 现在让我们看看如何使用lambda来做同样的事情。 我们从相同的基本组件对象开始:

public interface Pizza {String bakePizza();
}public class BasicPizza implements Pizza {@Overridepublic String bakePizza() {return "Basic Pizza";}
}

但是现在,我们不再声明一个抽象类来提供装饰的模板,而是创建一个装饰器,该装饰器要求用户提供装饰组件的功能。

public class PizzaDecorator {private final Function<Pizza, Pizza> toppings;private PizzaDecorator(Function<Pizza, Pizza>... desiredToppings) {this.toppings = Stream.of(desiredToppings).reduce(Function.identity(), Function::andThen);}public static String bakePizza(Pizza pizza, Function<Pizza, Pizza>... desiredToppings) {return new PizzaDecorator(desiredToppings).bakePizza(pizza);}private String bakePizza(Pizza pizza) {return this.toppings.apply(pizza).bakePizza();
}}

这条线构成了要应用的装饰链:

Stream.of(desiredToppings).reduce(identity(), Function::andThen);

这行代码将接受您的装饰(属于Function类型),并使用andThen链接它们。 这和

(currentToppings, nextTopping) -> currentToppings.andThen(nextTopping)

并确保随后按您提供的顺序调用这些函数。 还将Function.identity()转换为elem-> elem lambda表达式。 好的,现在我们在哪里定义装饰? 您可以在PizzaDecorator甚至在界面中将它们添加为静态方法:

public interface Pizza {String bakePizza();static Pizza withChickenTikka(Pizza pizza) {return new Pizza() {@Overridepublic String bakePizza() {return pizza.bakePizza() + " with chicken";}};}static Pizza withProsciutto(Pizza pizza) {return new Pizza() {@Overridepublic String bakePizza() {return pizza.bakePizza() + " with prosciutto";}};}
}

现在,这就是这种模式的使用方式:

String finishedPizza = PizzaDecorator.bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);//And if you static import PizzaDecorator.bakePizza:String finishedPizza  = bakePizza(new BasicPizza(),Pizza::withChickenTikka, Pizza::withProsciutto);

如您所见,代码变得更加清晰和简洁,我们没有使用继承来构建我们的装饰器。

这只是可以使用lambda改进的众多设计模式之一。 还有更多功能可用来改善其余功能,例如使用部分应用程序(循环)来实现适配器模式。

希望我能引起您考虑对您的开发风格采用功能更强大的编程方法的想法。

参考书目

装饰器示例的灵感来自“ 四人帮” –“用装饰器设计模式进行装饰”一文。

重构方法是受以下Devoxx 2015演讲的启发(我建议在观看这些演讲时将其视为主题): Remi Forax重新加载的 设计模式,Venkat Subramaniam的Lambda表达形式的设计模式

翻译自: https://www.javacodegeeks.com/2015/12/decorator-design-pattern-using-lambdas.html

使用Lambda的装饰设计模式相关推荐

  1. 黑马程序员-JAVA基础-IO流中的装饰设计模式

    ------- android培训.java培训.期待与您交流!------- 装饰设计模式: 当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能.那么,自 ...

  2. 设计模式(二)__装饰设计模式

    今天呢,来给大家介绍一下装饰设计模式,java中IO就使用到了这个模式. 装饰设计模式,顾名思义,就是对一个功能进行装饰,就跟女人化妆一样,人还是本人,但是化了妆就变得比原来更漂亮了. 需求:当你有个 ...

  3. 黑马程序员:java基础之装饰设计模式

    一.什么是装饰设计模式 当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的类成为装饰类. 装饰类通常会通过构造方法,传递进来一个需要装饰的对象, ...

  4. day19(中)_IO流3(模拟缓冲区,装饰设计模式)

    1.MyBufferedReader和MyBufferedInputStream 1.模拟字符读取流的缓冲区: /*根据readLine原理:自定义一个类包含一个功能和readLine一致的方法来模拟 ...

  5. java经典设计模式4,JAVA设计模式(4) 之装饰设计模式

    在现实生活中我们的汽车都具备跑的功能,我们可以不改变汽车原有功能的前提下,把它放入一个装修厂,开进去让里面给咱们的车子做一些装饰,开出来之后呢,就具备了上天的功能了(技术可达是可以的哈),这就给原来的 ...

  6. java中的装饰模式讲解,java 中设计模式(装饰设计模式)的实例详解

    搜索热词 java 中设计模式(装饰设计模式)的实例详解 应用场景: 在不对原有对象类进行修改的基础上,给一个或多个已有的类对象提供增强额外的功能. 我觉得可以从字面理解,装饰,装饰房子.房子可以看成 ...

  7. 2016版连接池和装饰设计模式保存记录

    连接池 这里写图片描述 数据库连接池负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接.释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗 ...

  8. 装饰设计模式缓冲流转换流序列化与反序列化

    装饰设计模式&缓冲流&转换流&序列化与反序列化 - 能够使用字节缓冲流读取数据到程序1.创建BufferedInputStream对象,构造方法中传递FileInputStre ...

  9. JavaSE(字符流、IO资源的处理、属性集、ResourceBundle工具类、缓冲流、转换流、序列化、打印流、装饰设计模式、commons-io工具包)

    JavaSE 字符流 字符输入流[Reader] 字符输入流Reader类的概述 字符输入流Reader类的常用方法 FileReader类 FileReader类的概述 FileReader类的构造 ...

最新文章

  1. Unsafe工具类的一些实用技巧,通往JVM底层的钥匙
  2. c语言 程序 作文,编程之乐作文600字
  3. CodeMirror的使用方法
  4. sqlserver的技术规格
  5. 未检测到正确安装的网络适配器_电脑网络适配器有感叹号怎么解决?
  6. c语言 字符串 url,如何对URL字符串进行百分号编码
  7. 内存还剩余很多,却使用 swap 分区
  8. MySQL--My.cnf配置文件模板 MYSQL AND MARIADB CONFIGURATION FILE TEMPLATE (MY.CNF/MY.INI)
  9. 更新mac系统中homebrew的源,更改为清华大学的源
  10. Web前端工作笔记002---$(function(){})和$(document).ready(function(){}) 的区别
  11. PCIE万兆网卡-华硕XG-C100C
  12. MySQL group by语句用法
  13. MyBatis mapper parameterType
  14. 翱翔云天的SAP技术课程体系
  15. Stolz定理及其证明
  16. 自称骇客的基本都是骗子
  17. python stdin stdout_Python子进程:给出stdin,读取stdout,然后给出更多stdin
  18. TCP/IP协议栈 路由器 交换机
  19. KlipC数据显示2022年日元兑美元汇率有进一步下跌的风险和可能性
  20. 【SVAC】千目聚云:SVAC2.0已来 未来发展道路一片光明

热门文章

  1. 使用C#操作XML文件
  2. 2018蓝桥杯省赛---java---B---3(复数幂)
  3. html表格转换为csv,python实现将html表格转换成CSV文件的方法
  4. ibatis(0)ibatis 与 mybatis 简述
  5. jvm(6)-java类文件结构(字节码文件)
  6. apache derby_Apache Derby数据库JVM安全策略
  7. react提交数据到数据库_React型关系数据库事务
  8. java ee的小程序_在Java EE应用程序中实现自动重试
  9. 香辣弹簧:不同的自动接线方式
  10. gradle maven_将工件从Gradle自动提升到Maven Central