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

一、策略模式

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

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

OrderService接口:

public interface OrderService {
void saveOrder(String orderNo);
}

Mysql策略实现:

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

Nosql策略实现

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

使用策略的辅助"容器"

public class OrderServiceExecutor {

    private final OrderService service;

    public OrderServiceExecutor(OrderService service) {
this.service = service;
} public void save(String orderNo) {
this.service.saveOrder(orderNo);
} }  

运行测试类:

public class OrderServiceTest {
public static void main(String[] args) {
OrderServiceExecutor executor1 = new OrderServiceExecutor(new MySqlSaveOrderStrategy());
executor1.save("001");
OrderServiceExecutor executor2 = new OrderServiceExecutor(new NoSqlSaveOrderStrategy());
executor2.save("002");
}
}  

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

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

二、模板方法

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

抽象模板类:

public abstract class AbstractPushTemplate {

    public void push(int customerId, String shopName) {
System.out.println("准备推送...");
execute(customerId, shopName);
System.out.println("推送完成\n");
} abstract protected void execute(int customerId, String shopName);
}

优惠券的具体模板

public class PushCouponTemplate extends AbstractPushTemplate {

    @Override
protected void execute(int customerId, String shopName) {
System.out.println("会员:" + customerId + ",你好," + shopName + "送您一张优惠券");
}
}

积分的具体模板

public class PushScoreTemplate extends AbstractPushTemplate {

    @Override
protected void execute(int customerId, String shopName) {
System.out.println("会员:" + customerId + ",你好," + shopName + "送您10个积分");
}
}

使用示例:

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

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

public class PushTemplateLambda {

    public void push(int customerId, String shopName, Consumer<Object[]> execute) {
System.out.println("准备推送...");
Object[] param = new Object[]{customerId, shopName};
execute.accept(param);
System.out.println("推送完成\n");
}
}

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

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

  

三、观察者模式

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

Observer接口:

public interface Observer {
void notify(String orderNo);
}

Subject接口:

public interface Subject {
void registerObserver(Observer o);
void notifyAllObserver(String orderNo);
}

Subject接口实现:

public class SubjectImpl implements Subject {
private final List<Observer> list = new ArrayList<>();
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void notifyAllObserver(String orderNo) {
list.forEach(c -> c.notify(orderNo));
}
}  

观察者的二个实现:

OrderObserver:

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

StockObserver:

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

测试一把:

    static void test1() {
Subject subject = new SubjectImpl();
subject.registerObserver(new OrderObserver());
subject.registerObserver(new StockObserver());
subject.notifyAllObserver("001");
}  

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

public interface NewSubject {

    List<Observer> list = new ArrayList<>();

    default void registerObserver(Observer o) {
list.add(o);
} default void nofityAllObserver(String orderNo) {
list.forEach(c -> c.notify(orderNo));
}
}

使用:

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

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

  

四、责任链/职责链模式

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

Processor接口:

public interface Processor {

    Processor getNextProcessor();

    void process(String param);
}

抽象实现类

public abstract class AbstractProcessor implements Processor {

    private Processor next;

    public AbstractProcessor(Processor processor) {
this.next = processor;
} @Override
public Processor getNextProcessor() {
return next;
} @Override
public abstract void process(String param);
}

定义2个具体的实现

public class ProcessorImpl1 extends AbstractProcessor {

    public ProcessorImpl1(Processor processor) {
super(processor);
} @Override
public void process(String param) {
System.out.println("processor 1 is processing:" + param);
if (getNextProcessor() != null) {
getNextProcessor().process(param);
}
}
}

public class ProcessorImpl2 extends AbstractProcessor {

    public ProcessorImpl2(Processor next) {
super(next);
} @Override
public void process(String param) {
System.out.println("processor 2 is processing:" + param);
if (getNextProcessor() != null) {
getNextProcessor().process(param);
}
}
}

使用示例:

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

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

@FunctionalInterface
public interface NewProcessor {
Consumer<String> process(String param);
}

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

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

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. apache服务器的常用功能及设置

    安装httpd yum -y install  httpd     服务脚本:/etc/rc.d/init.d/httpd        脚本配置文件:/etc/sysconfig/httpd     ...

  2. Linux中断处理(一)

    最近在研究异步消息处理, 突然想起linux内核的中断处理, 里面由始至终都贯穿着"重要的事马上做, 不重要的事推后做"的异步处理思想. 于是整理一下~~第一阶段--获取中断号每个 ...

  3. MySQL 数据类型(转)

    MySQL 数据类型 在 MySQL 中,有三种主要的类型:文本.数字和日期/时间类型. Text 类型: 数据类型 描述 备注 CHAR(size) 保存固定长度的字符串(可包含字母.数字以及特殊字 ...

  4. Python-html css 盒模型

    <!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>ht ...

  5. Python-生产者消费模型 线程

    7.生产者消费者模型(*****)(思聪吃热狗代码) 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题. 该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度 为什么要使 ...

  6. C#面向对象(基础知识)

    面向对象:就是CLASS,class就是用户自定义类型: class:用户自定义引用类型:三大特点:封装.继承.多态: 解决方案中右键添加class:class内可以写结构体,枚举,函数: C#中各个 ...

  7. STM32应用实例八:与多台MS5803压力传感器I2C通讯

    MS5803压力传感器支持SPI和I2C总线通讯,拥有24位AD转换.能够同时获得压力值和温度值,其中压力测量范围为10-1100mbar,温度的测量范围是-40-85摄氏度.各引脚功能及参数如下: ...

  8. 性能测试十四:Xshell链接linux虚拟机

    一.先装一个linux虚拟机 VBox+centos1.先下载Linux镜像文件的ovf或者OVA文件2.打开vbox,点击菜单栏“管理”-“导入虚拟电脑3.选择解压路径中的ovf或者OVA文件,点击 ...

  9. java web项目为什么我们要放弃jsp?

    前戏: 以前的项目大多数都是java程序猿又当爹又当妈,又搞前端(ajax/jquery/js/html/css等等),又搞后端(java/mysql/Oracle等等). 随着时代的发展,渐渐的许多 ...

  10. 步步为营-63-Asp.net-get与post

    1 get Get方式将数据发送到服务端,那么会将用户在表单中的数据放置到浏览器的地址栏中发送到服务器 格式:表单元素name属性的值=用户输入的值 请求地址:http://localhost:594 ...