java8中提供的很多新特性可以用来重构传统设计模式中的写法,下面是一些示例:

一、策略模式

上图是策略模式的类图,假设我们现在要保存订单,OrderService接口定义要做什么,而NoSqlSaveOrderStragegy以及MySqlSaveOrderStrategy则提供了二种策略,分别是保存到nosql数据库,以及传统的mysql关系型数据库,最后在OrderServiceExecutor中通过构造函数注入最终要使用的策略。

传统写法,这个场景至少得4个类,代码如下:

OrderService接口:

  1. public interface OrderService {
  2. void saveOrder(String orderNo);
  3. }

Mysql策略实现:

  1. public class MySqlSaveOrderStrategy implements OrderService {
  2. @Override
  3. public void saveOrder(String orderNo) {
  4. System.out.println("order:" + orderNo + " save to mysql");
  5. }
  6. }

Nosql策略实现

  1. public class NoSqlSaveOrderStrategy implements OrderService {
  2. @Override
  3. public void saveOrder(String orderNo) {
  4. System.out.println("order:" + orderNo + " save to nosql");
  5. }
  6. } 

使用策略的辅助"容器"

  1. public class OrderServiceExecutor {
  2.  
  3. private final OrderService service;
  4.  
  5. public OrderServiceExecutor(OrderService service) {
  6. this.service = service;
  7. }
  8.  
  9. public void save(String orderNo) {
  10. this.service.saveOrder(orderNo);
  11. }
  12.  
  13. }  

运行测试类:

  1. public class OrderServiceTest {
  2. public static void main(String[] args) {
  3. OrderServiceExecutor executor1 = new OrderServiceExecutor(new MySqlSaveOrderStrategy());
  4. executor1.save("001");
  5. OrderServiceExecutor executor2 = new OrderServiceExecutor(new NoSqlSaveOrderStrategy());
  6. executor2.save("002");
  7. }
  8. }  

重构后,可以省去2个策略实现类,代码如下:

  1. public static void main(String[] args) {
  2. OrderServiceExecutor executor1 = new OrderServiceExecutor((String orderNo) -> System.out.println("order:" + orderNo + " save to mysql"));
  3. executor1.save("001");
  4.  
  5. OrderServiceExecutor executor2 = new OrderServiceExecutor((String orderNo) -> System.out.println("order:" + orderNo + " save to nosql"));
  6. executor2.save("002");
  7. }

二、模板方法

类图如下,核心思路是把一些通用的标准方法,在抽象父类里仅定义方法签名,实现逻辑交给子类。比如:会员系统中,每个商家都会有一些营销活动,需要推送某种信息给会员,但是不同的商家推送的内容可能不同,有些需要推送优惠券,有些需要积分通知。

抽象模板类:

  1. public abstract class AbstractPushTemplate {
  2.  
  3. public void push(int customerId, String shopName) {
  4. System.out.println("准备推送...");
  5. execute(customerId, shopName);
  6. System.out.println("推送完成\n");
  7. }
  8.  
  9. abstract protected void execute(int customerId, String shopName);
  10. }

优惠券的具体模板

  1. public class PushCouponTemplate extends AbstractPushTemplate {
  2.  
  3. @Override
  4. protected void execute(int customerId, String shopName) {
  5. System.out.println("会员:" + customerId + ",你好," + shopName + "送您一张优惠券");
  6. }
  7. }

积分的具体模板

  1. public class PushScoreTemplate extends AbstractPushTemplate {
  2.  
  3. @Override
  4. protected void execute(int customerId, String shopName) {
  5. System.out.println("会员:" + customerId + ",你好," + shopName + "送您10个积分");
  6. }
  7. }

使用示例:

  1. AbstractPushTemplate template1 = new PushCouponTemplate();
  2. template1.push(1, "糖果店");
  3.  
  4. AbstractPushTemplate template2 = new PushScoreTemplate();
  5. template2.push(1, "服装店");  

显然如果模板的实现方式越多,子类就越多。使用java8重构后,可以把上面的3个模板(包括抽象类模板)减少到1个,参考下面:

  1. public class PushTemplateLambda {
  2.  
  3. public void push(int customerId, String shopName, Consumer<Object[]> execute) {
  4. System.out.println("准备推送...");
  5. Object[] param = new Object[]{customerId, shopName};
  6. execute.accept(param);
  7. System.out.println("推送完成\n");
  8. }
  9. }

借助Consumer<T>这个function interface,可以省去实现子类,具体的实现留到使用时再来决定,如:

  1. new PushTemplateLambda().push(1, "糖果店", (Object[] obj) -> {
  2. System.out.println("会员:" + obj[0] + ",你好," + obj[1] + "送您一张优惠券");
  3. });
  4.  
  5. new PushTemplateLambda().push(1, "服装店", (Object[] obj) -> {
  6. System.out.println("会员:" + obj[0] + ",你好," + obj[1] + "送您10个积分");
  7. });

  

三、观察者模式

思路:基于某个Subject主题,然后一堆观察者Observer注册到主题上,有事件发生时,subject根据注册列表,去通知所有的observer。

Observer接口:

  1. public interface Observer {
  2. void notify(String orderNo);
  3. }

Subject接口:

  1. public interface Subject {
  2. void registerObserver(Observer o);
  3. void notifyAllObserver(String orderNo);
  4. }

Subject接口实现:

  1. public class SubjectImpl implements Subject {
  2. private final List<Observer> list = new ArrayList<>();
  3. @Override
  4. public void registerObserver(Observer o) {
  5. list.add(o);
  6. }
  7. @Override
  8. public void notifyAllObserver(String orderNo) {
  9. list.forEach(c -> c.notify(orderNo));
  10. }
  11. }  

观察者的二个实现:

OrderObserver:

  1. public class OrderObserver implements Observer {
  2. @Override
  3. public void notify(String orderNo) {
  4. System.out.println("订单 " + orderNo + " 状态更新为【已支付】");
  5. }
  6. }

StockObserver:

  1. public class StockObserver implements Observer {
  2. @Override
  3. public void notify(String orderNo) {
  4. System.out.println("订单 " + orderNo + " 已通知库房发货!");
  5. }
  6. }

测试一把:

  1. static void test1() {
  2. Subject subject = new SubjectImpl();
  3. subject.registerObserver(new OrderObserver());
  4. subject.registerObserver(new StockObserver());
  5. subject.notifyAllObserver("001");
  6. }  

用java8重构后,接口可以提供默认实现方法,我们弄一个新的主题接口

  1. public interface NewSubject {
  2.  
  3. List<Observer> list = new ArrayList<>();
  4.  
  5. default void registerObserver(Observer o) {
  6. list.add(o);
  7. }
  8.  
  9. default void nofityAllObserver(String orderNo) {
  10. list.forEach(c -> c.notify(orderNo));
  11. }
  12. }

使用:

  1. static void test2() {
  2. NewSubject subject = new NewSubject() {
  3. };
  4. subject.registerObserver((String orderNo) -> System.out.println("订单 " + orderNo + " 状态更新为【已支付】"));
  5. subject.registerObserver((String orderNo) -> System.out.println("订单 " + orderNo + " 已通知库房发货!"));
  6. subject.nofityAllObserver("002");
  7. }

只用2个接口实现了观察者模式。  

  

四、责任链/职责链模式

核心思想:每个处理环节,都有一个“指针”指向下一个处理者,类似链表一样。

Processor接口:

  1. public interface Processor {
  2.  
  3. Processor getNextProcessor();
  4.  
  5. void process(String param);
  6. }

抽象实现类

  1. public abstract class AbstractProcessor implements Processor {
  2.  
  3. private Processor next;
  4.  
  5. public AbstractProcessor(Processor processor) {
  6. this.next = processor;
  7. }
  8.  
  9. @Override
  10. public Processor getNextProcessor() {
  11. return next;
  12. }
  13.  
  14. @Override
  15. public abstract void process(String param);
  16. }

定义2个具体的实现

  1. public class ProcessorImpl1 extends AbstractProcessor {
  2.  
  3. public ProcessorImpl1(Processor processor) {
  4. super(processor);
  5. }
  6.  
  7. @Override
  8. public void process(String param) {
  9. System.out.println("processor 1 is processing:" + param);
  10. if (getNextProcessor() != null) {
  11. getNextProcessor().process(param);
  12. }
  13. }
  14. }

  1. public class ProcessorImpl2 extends AbstractProcessor {
  2.  
  3. public ProcessorImpl2(Processor next) {
  4. super(next);
  5. }
  6.  
  7. @Override
  8. public void process(String param) {
  9. System.out.println("processor 2 is processing:" + param);
  10. if (getNextProcessor() != null) {
  11. getNextProcessor().process(param);
  12. }
  13. }
  14. }

使用示例:

  1. static void test1() {
  2. Processor p1 = new ProcessorImpl1(null);
  3. Processor p2 = new ProcessorImpl2(p1);
  4. p2.process("something happened");
  5. }

用java8重构后,只需要一个新接口

  1. @FunctionalInterface
  2. public interface NewProcessor {
  3. Consumer<String> process(String param);
  4. }

同样的效果,可以写得很简洁:

  1. static void test2() {
  2. Consumer<String> p1 = param -> System.out.println("processor 1 is processing:" + param);
  3. Consumer<String> p2 = param -> System.out.println("processor 2 is processing:" + param);
  4. p2.andThen(p1).accept("something happened");
  5. }

andThen天然就是getNextProcessor的另一种表达。

重要提示:什么时候该用lambda,什么时候不用,这是要看情况的,如果处理逻辑相对比较简单,可以用lamdba来重构,以便让代码更简洁易读,如果处理逻辑很复杂,应该还是用“类”。

利用java8对设计模式的重构的更多相关文章

  1. 利用js日期控件重构WEB功能

    开发需求:网页中的日期部门(注册页面和查询条件)都用js日期控件重写 页面一:更新员工页面 empUpdate.jsp 中增加 onfocus 事件 入职日期:<input id="h ...

  2. 利用java8新特性,用简洁高效的代码来实现一些数据处理

    定义1个Apple对象: public class Apple {    private Integer id;    private String name;    private BigDecim ...

  3. 图解如何利用Intellij IDEA进行代码重构

    源:https://jingyan.baidu.com/article/c45ad29c64f7e7051653e27d.html 重命名类,打开 Refactor -> Rename 或 Sh ...

  4. python:爬虫入门

    直接上代码吧: 一.爬取某外卖平台的指定商家菜品信息 from urllib import request import json import random url = "https:// ...

  5. 利用vue-router和compoment重构代码--踩坑(一)

    业务主要功能 获取所有的数据库列表 点击某一个数据库列表的时候,右侧分页展示数据 点击右侧某一条数据的时候,现实数据详情 以下是之前的页面,存在以下问题: 前段开发没有工程化(webpack) 主要功 ...

  6. 设计模式 AOP,OOP

    AOP.OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想. 简单说,AOP面向动词领域,OOP面向名词领域 AOP: (Aspect Oriented Programming) 面向切面编 ...

  7. 面向对象设计模式纵横谈:Singelton单件模式(笔记记录)

       李建忠老师讲的<面向对象设计模式纵横谈>,早就看过了,现在有了时间重新整理一下,以前的博客[赛迪网]没有了,现在搬到博客园,重新过一遍,也便于以后浏览. 设计模式从不同的角度分类会得 ...

  8. Java8并发教程:Threads和Executors

    来之:ImportNew 欢迎阅读我的Java8并发教程的第一部分.这份指南将会以简单易懂的代码示例来教给你如何在Java8中进行并发编程.这是一系列教程中的第一部分.在接下来的15分钟,你将会学会如 ...

  9. 大话设计模式C++版——原则和引言

    转贴请注明转自:http://blog.csdn.net/gufeng99/article/details/45832711 读程杰的<大话设计模式>有一段时间了,将其C#版的设计模式代码 ...

随机推荐

  1. centos7的安装主要步骤选择

    选择语言,选择英语 选择时区done确认选择 安全策略,选择默认 安装源文件 软件包选择,此处选择 最小安装 选择磁盘,并分区

  2. 如何在CentOS 7上安装Munin

    在CentOS 7上安装Munin 首先我们需要在我们的系统中添加EPEL仓库. yum install epel-release 步骤2.安装LAMP(Linux,Apache,MariaDB,PH ...

  3. js学习、备忘

    字符串使用单引号’abc’.(双引号也行.推荐:html→双引号,js→单引号)===严格等于.!==严格不等于if(x)  当x为undefined.null和0的时候都为false:需注意当x为0 ...

  4. windows下升级node&npm

    一.升级npm npm install -g npm 二.升级node 1.查询node的安装目录 where node 2.在官网下载最新的安装包,直接覆盖安装即可. https://nodejs. ...

  5. Redhat5_linux 系统环境下 oracl11g的安装教程图解

    linux_oracl11g 安装步骤 操作系统的安装敬请参考此文:VM 安装 linux Enterprise_R5_U4_Server_I386_DVD教程图解 设置linux服务器的静态地址请参 ...

  6. wampserver修改端口号后,phpMyAdmin进不去,需要修改相关配置文件

    一.修改Apache端口 1.在界面中选Apache,弹出隐藏菜单选项,打开配置文件httpd.conf: 2.找到 Listen 80: 3.将 80 改成 8080(当然自己也可以设定别的不使用的 ...

  7. BZOJ1297 [SCOI2009]迷路 矩阵乘法

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1297 题意概括 有向图有 N 个节点,从节点 0 出发,他必须恰好在 T 时刻到达节点 N-1. ...

  8. 004 Spark中的local模式的配置以及测试

    一:介绍 1.Spark的模式 Local:本地运行模式,主要用于开发.测试 Standalone:使用Spark自带的资源管理框架运行Spark程序,30%左右 Yarn: 将spark应用程序运行 ...

  9. Unity Standard Assets Example Project

    参考链接:http://blog.csdn.net/jaikydota163/article/details/52751976

  10. 《Gradle权威指南》--Gradle任务

    No1: 多种方式创建任务 def Task ex41CreateTask1 = task(ex41CreateTask1) ex41CreateTask1.doLast{ println " ...